ZQuest Classic Coverage Report


Directory: src/
File: src/zq/zq_tiles.cpp
Date: 2024-05-02 01:19:50
Exec Total Coverage
Lines: 93 7622 1.2%
Functions: 1 194 0.5%
Branches: 9 6341 0.1%

Line Branch Exec Source
1 #include <cstring>
2 #include <cmath>
3
4 #include "base/qrs.h"
5 #include "base/dmap.h"
6 #include "base/cpool.h"
7 #include "base/autocombo.h"
8 #include "base/packfile.h"
9 #include "base/gui.h"
10 #include "base/combo.h"
11 #include "base/msgstr.h"
12 #include "base/zdefs.h"
13 #include "zq/zquestdat.h"
14 #include "zq/zq_tiles.h"
15 #include "zq/zquest.h"
16 #include "tiles.h"
17 #include "zq/zq_misc.h"
18 #include "zq/zq_class.h"
19 #include "base/zsys.h"
20 #include "base/colors.h"
21 #include "qst.h"
22 #include "gui/jwin.h"
23 #include <base/new_menu.h>
24 #include "base/jwinfsel.h"
25 #include "zc/zc_custom.h"
26 #include "zq/questReport.h"
27 #include "dialog/info.h"
28 #include "dialog/scaletile.h"
29 #include "dialog/rotatetile.h"
30 #include "dialog/alert.h"
31 #include "drawing.h"
32 #include "colorname.h"
33 #include "zq/render.h"
34 #include "zinfo.h"
35 #include <fmt/format.h>
36 #include "zq/moveinfo.h"
37 using std::set;
38
39 extern zcmodule moduledata;
40
41 #ifdef _MSC_VER
42 #define stricmp _stricmp
43 #endif
44
45 #define HIDE_USED (show_only_unused_tiles&1)
46 #define HIDE_UNUSED (show_only_unused_tiles&2)
47 #define HIDE_BLANK (show_only_unused_tiles&4)
48 #define HIDE_8BIT_MARKER (show_only_unused_tiles&8)
49
50 extern void large_dialog(DIALOG *d);
51 static void massRecolorReset4Bit();
52 static void massRecolorReset8Bit();
53 static bool massRecolorSetup(int32_t cset);
54 static void massRecolorApply(int32_t tile);
55 extern int32_t last_droplist_sel;
56 extern int32_t TilePgCursorCol, CmbPgCursorCol;
57
58 int32_t ex=0;
59 int32_t nextcombo_fake_click=0;
60 int32_t invcol=0;
61 int32_t tthighlight = 1;
62 int32_t showcolortip = 1;
63 int32_t show_quartgrid = 0, hide_grid = 0;
64
65 tiledata *newundotilebuf;
66 std::vector<newcombo> undocombobuf;
67
68 BITMAP *selection_pattern;
69 byte selection_grid[18][18];
70 byte selection_anchor=0;
71
72 enum {selection_mode_normal, selection_mode_add, selection_mode_subtract, selection_mode_exclude};
73 BITMAP *selecting_pattern;
74 int32_t selecting_x1, selecting_x2, selecting_y1, selecting_y2;
75
76 extern int32_t bidcomboscripts_cnt;
77 extern script_struct bidcomboscripts[NUMSCRIPTSCOMBODATA];
78
79 BITMAP *intersection_pattern;
80
81 byte relational_template[48][4]=
82 {
83 { 0, 0, 0, 0 },
84 { 0, 1, 0, 0 },
85 { 1, 0, 0, 0 },
86 { 1, 1, 0, 0 },
87 { 0, 0, 1, 0 },
88 { 0, 1, 1, 0 },
89 { 1, 0, 1, 0 },
90 { 1, 1, 1, 0 },
91 { 0, 0, 0, 1 },
92 { 0, 1, 0, 1 },
93 { 1, 0, 0, 1 },
94 { 1, 1, 0, 1 },
95 { 0, 0, 1, 1 },
96 { 0, 1, 1, 1 },
97 { 1, 0, 1, 1 },
98 { 1, 1, 1, 1 },
99 { 0, 2, 0, 2 },
100 { 1, 2, 0, 2 },
101 { 0, 2, 1, 2 },
102 { 1, 2, 1, 2 },
103 { 3, 3, 0, 0 },
104 { 3, 3, 1, 0 },
105 { 3, 3, 0, 1 },
106 { 3, 3, 1, 1 },
107 { 3, 4, 0, 2 },
108 { 3, 4, 1, 2 },
109 { 2, 0, 2, 0 },
110 { 2, 1, 2, 0 },
111 { 2, 0, 2, 1 },
112 { 2, 1, 2, 1 },
113 { 2, 2, 2, 2 },
114 { 4, 3, 2, 0 },
115 { 4, 3, 2, 1 },
116 { 4, 4, 2, 2 },
117 { 0, 0, 3, 3 },
118 { 0, 1, 3, 3 },
119 { 1, 0, 3, 3 },
120 { 1, 1, 3, 3 },
121 { 0, 2, 3, 4 },
122 { 1, 2, 3, 4 },
123 { 3, 3, 3, 3 },
124 { 3, 4, 3, 4 },
125 { 2, 0, 4, 3 },
126 { 2, 1, 4, 3 },
127 { 2, 2, 4, 4 },
128 { 4, 3, 4, 3 },
129 { 4, 4, 4, 4 },
130 { 5, 5, 5, 5 }
131 };
132
133 byte dungeon_carving_template[96][4]=
134 {
135 { 0, 0, 0, 0 },
136 { 0, 1, 0, 0 },
137 { 1, 0, 0, 0 },
138 { 1, 1, 0, 0 },
139 { 0, 0, 1, 0 },
140 { 0, 1, 1, 0 },
141 { 1, 0, 1, 0 },
142 { 1, 1, 1, 0 },
143 { 0, 0, 0, 1 },
144 { 0, 1, 0, 1 },
145 { 1, 0, 0, 1 },
146 { 1, 1, 0, 1 },
147 { 0, 0, 1, 1 },
148 { 0, 1, 1, 1 },
149 { 1, 0, 1, 1 },
150 { 1, 1, 1, 1 },
151 { 0, 2, 0, 2 },
152 { 1, 2, 0, 2 },
153 { 0, 2, 1, 2 },
154 { 1, 2, 1, 2 },
155 { 3, 3, 0, 0 },
156 { 3, 3, 1, 0 },
157 { 3, 3, 0, 1 },
158 { 3, 3, 1, 1 },
159 { 3, 4, 0, 2 },
160 { 3, 4, 1, 2 },
161 { 2, 0, 2, 0 },
162 { 2, 1, 2, 0 },
163 { 2, 0, 2, 1 },
164 { 2, 1, 2, 1 },
165 { 2, 2, 2, 2 },
166 { 4, 3, 2, 0 },
167 { 4, 3, 2, 1 },
168 { 4, 4, 2, 2 },
169 { 0, 0, 3, 3 },
170 { 0, 1, 3, 3 },
171 { 1, 0, 3, 3 },
172 { 1, 1, 3, 3 },
173 { 0, 2, 3, 4 },
174 { 1, 2, 3, 4 },
175 { 3, 3, 3, 3 },
176 { 3, 4, 3, 4 },
177 { 2, 0, 4, 3 },
178 { 2, 1, 4, 3 },
179 { 2, 2, 4, 4 },
180 { 4, 3, 4, 3 },
181 { 4, 4, 4, 4 },
182 { 5, 5, 5, 5 },
183
184 { 5, 5, 5, 5 },
185 { 6, 6, 6, 6 },
186 { 7, 7, 7, 7 },
187 { 7, 6, 7, 6 },
188 { 8, 8, 8, 8 },
189 { 16, 6, 8, 15 },
190 { 7, 7, 8, 8 },
191 { 7, 6, 8, 15 },
192 { 9, 9, 9, 9 },
193 { 6, 6, 9, 9 },
194 { 7, 17, 14, 9 },
195 { 7, 6, 14, 9 },
196 { 8, 9, 8, 9 },
197 { 16, 6, 8, 9 },
198 { 7, 17, 8, 9 },
199 { 7, 6, 8, 9 },
200 { 10, 10, 10, 10 },
201 { 7, 10, 14, 10 },
202 { 16, 10, 8, 10 },
203 { 7, 10, 8, 10 },
204 { 11, 11, 11, 11 },
205 { 11, 11, 8, 15 },
206 { 11, 11, 14, 9 },
207 { 11, 11, 8, 9 },
208 { 14, 14, 14, 14 },
209 { 14, 14, 8, 14 },
210 { 12, 12, 12, 12 },
211 { 12, 6, 12, 15 },
212 { 12, 17, 12, 9 },
213 { 12, 6, 12, 9 },
214 { 12, 10, 12, 10 },
215 { 15, 15, 15, 15 },
216 { 15, 15, 15, 9 },
217 { 15, 14, 12, 10 },
218 { 13, 13, 13, 13 },
219 { 16, 6, 13, 13 },
220 { 7, 17, 13, 13 },
221 { 7, 6, 13, 13 },
222 { 16, 16, 16, 16 },
223 { 7, 16, 16, 16 },
224 { 11, 11, 13, 13 },
225 { 11, 14, 13, 16 },
226 { 17, 17, 17, 17 },
227 { 17, 6, 17, 17 },
228 { 12, 10, 17, 16 },
229 { 15, 11, 17, 13 },
230 { 15, 14, 17, 16 },
231 { 18, 18, 18, 18 }
232 };
233
234 struct tile_move_data
235 {
236 int32_t copies;
237 int32_t dest_first;
238 int32_t dest_last;
239 int32_t src_first;
240 int32_t src_last;
241 int32_t dest_top;
242 int32_t dest_bottom;
243 int32_t src_top;
244 int32_t src_bottom;
245 int32_t src_left, src_right;
246 int32_t src_width, src_height;
247 int32_t dest_left, dest_right;
248 int32_t dest_width, dest_height;
249 int32_t rows, cols;
250 bool rect, move;
251
252 tile_move_data()
253 {
254 copies = dest_first = dest_last = src_first = src_last = dest_top =
255 dest_bottom = src_top = src_bottom = src_left = src_right =
256 src_width = src_height = dest_left = dest_right = dest_width =
257 dest_height = rows = cols = 0;
258 rect = move = false;
259 }
260
261 tile_move_data(tile_move_data const& other)
262 {
263 copy(other);
264 }
265
266 tile_move_data& operator=(tile_move_data const& other)
267 {
268 copy(other);
269 return *this;
270 }
271
272 void copy(tile_move_data const& other)
273 {
274 copies = other.copies;
275 dest_first = other.dest_first;
276 dest_last = other.dest_last;
277 src_first = other.src_first;
278 src_last = other.src_last;
279 dest_top = other.dest_top;
280 dest_bottom = other.dest_bottom;
281 src_top = other.src_top;
282 src_bottom = other.src_bottom;
283 src_left = other.src_left;
284 src_right = other.src_right;
285 src_width = other.src_width;
286 src_height = other.src_height;
287 dest_left = other.dest_left;
288 dest_right = other.dest_right;
289 dest_width = other.dest_width;
290 dest_height = other.dest_height;
291 rows = other.rows;
292 cols = other.cols;
293 rect = other.rect;
294 move = other.move;
295 }
296
297 void flip()
298 {
299 zc_swap(src_first, dest_first);
300 zc_swap(src_last, dest_last);
301 zc_swap(src_top, dest_top);
302 zc_swap(src_bottom, dest_bottom);
303 zc_swap(src_left, dest_left);
304 zc_swap(src_right, dest_right);
305 zc_swap(src_width, dest_width);
306 zc_swap(src_height, dest_height);
307 }
308 };
309 bool do_movetile_united(tile_move_data const& tmd);
310
311 struct combo_move_data
312 {
313 int32_t tile, tile2, copy1, copycnt;
314 combo_move_data() : tile(0), tile2(0), copy1(0), copycnt(0){}
315 combo_move_data(combo_move_data const& other)
316 {
317 copy(other);
318 }
319 combo_move_data& operator=(combo_move_data const& other)
320 {
321 copy(other);
322 return *this;
323 }
324 void copy(combo_move_data const& other)
325 {
326 tile = other.tile;
327 tile2 = other.tile2;
328 copy1 = other.copy1;
329 copycnt = other.copycnt;
330 }
331
332 void flip()
333 {
334 int32_t tcnt = tile2-tile+1;
335 int32_t cpy2 = copy1+copycnt-1;
336 zc_swap(tile,copy1);
337 tile2 = cpy2;
338 copycnt = tcnt;
339 }
340 };
341
342 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing = false);
343 static optional<ComboMoveUndo> last_combo_move_list;
344 static optional<TileMoveUndo> last_tile_move_list;
345
346 int refl_flags = 0;
347 enum
348 {
349 REFL_90CW, REFL_HFLIP,
350 REFL_90CCW, REFL_VFLIP,
351 REFL_180, REFL_DBLFLIP,
352 REFL_MAX
353 };
354 const char *reflbtn_names[] =
355 {
356 "90 CW", "HFlip",
357 "90 CCW", "VFlip",
358 "180 Rot", "Diag Flip"
359 };
360 int bgmode = 0, xmode = 0;
361 const char *bgmodebtn_names[] =
362 {
363 "BG Color 0", "BG Trans."
364 };
365 const char *xmodebtn_names[] =
366 {
367 "X", "No X"
368 };
369 enum
370 {
371 XMODE_X, XMODE_NOX,
372 XMODE_MAX
373 };
374 enum
375 {
376 BGMODE_0, BGMODE_TRANSP,
377 BGMODE_MAX
378 };
379
380 /*********************************/
381 /***** Tiles & Combos ******/
382 /*********************************/
383
384 void merge_tiles(int32_t dest_tile, int32_t src_quarter1, int32_t src_quarter2, int32_t src_quarter3, int32_t src_quarter4)
385 {
386 int32_t size=tilesize(newtilebuf[dest_tile].format)>>4;
387 int32_t size2=size>>1;
388
389 if(newtilebuf[dest_tile].data==NULL)
390 {
391 reset_tile(newtilebuf, dest_tile, newtilebuf[src_quarter1>>2].format);
392 }
393
394 int32_t i=0;
395
396 if((dest_tile<<2)+i!=src_quarter1)
397 {
398 for(int32_t j=0; j<8; ++j)
399 {
400 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter1>>2].data[((j+((src_quarter1&2)<<2))*size)+((src_quarter1&1)*size2)]), size2);
401 }
402 }
403
404 i=1;
405
406 if((dest_tile<<2)+i!=src_quarter2)
407 {
408 for(int32_t j=0; j<8; ++j)
409 {
410 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter2>>2].data[((j+((src_quarter2&2)<<2))*size)+((src_quarter2&1)*size2)]), size2);
411 }
412 }
413
414 i=2;
415
416 if((dest_tile<<2)+i!=src_quarter3)
417 {
418 for(int32_t j=0; j<8; ++j)
419 {
420 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter3>>2].data[((j+((src_quarter3&2)<<2))*size)+((src_quarter3&1)*size2)]), size2);
421 }
422 }
423
424 i=3;
425
426 if((dest_tile<<2)+i!=src_quarter4)
427 {
428 for(int32_t j=0; j<8; ++j)
429 {
430 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter4>>2].data[((j+((src_quarter4&2)<<2))*size)+((src_quarter4&1)*size2)]), size2);
431 }
432 }
433 }
434
435 static void make_combos(int32_t startTile, int32_t endTile, int32_t cs)
436 {
437 al_trace("inside make_combos()\n");
438 int32_t startCombo=0;
439
440 if(!select_combo_2(startCombo,cs))
441 return;
442
443 int32_t temp=combobuf[startCombo].o_tile;
444 combobuf[startCombo].set_tile(startTile);
445
446 if(!edit_combo(startCombo, false, cs))
447 {
448 combobuf[startCombo].set_tile(temp);
449 return;
450 }
451
452 go_combos();
453
454 for(int32_t i=0; i<=endTile-startTile; i++)
455 {
456 combobuf[startCombo+i]=combobuf[startCombo];
457 combobuf[startCombo+i].set_tile(startTile+i);
458 }
459
460 setup_combo_animations();
461 setup_combo_animations2();
462 }
463
464 static void make_combos_rect(int32_t top, int32_t left, int32_t numRows, int32_t numCols, int32_t cs)
465 {
466 //al_trace("inside make_combos_rect()\n");
467 int32_t startCombo=0;
468
469 if(!select_combo_2(startCombo, cs))
470 return;
471
472 int32_t startTile=top*TILES_PER_ROW+left;
473 int32_t temp=combobuf[startCombo].o_tile;
474 combobuf[startCombo].set_tile(startTile);
475
476 if(!edit_combo(startCombo, false, cs))
477 {
478 al_trace("make_combos_rect() early return\n");
479 combobuf[startCombo].set_tile(temp);
480 return;
481 }
482
483 bool smartWrap=false;
484 if(numCols!=4 && numRows>1)
485 {
486 char buf[64];
487 if(numCols<4)
488 sprintf(buf, "Limit to %d column%s?", numCols, numCols==1 ? "" : "s");
489 else
490 sprintf(buf, "Fit to 4 columns?"); // Meh, whatever.
491 int32_t ret=jwin_alert("Wrapping", buf, NULL, NULL, "&Yes", "&No", 'y', 'n', get_zc_font(font_lfont));
492 if(ret==1)
493 smartWrap=true;
494 }
495
496 go_combos();
497
498 int32_t combo=startCombo-1;
499 for(int32_t row=0; row<numRows; row++)
500 {
501 for(int32_t col=0; col<numCols; col++)
502 {
503 int32_t tile=startTile+row*TILES_PER_ROW+col;
504 if(smartWrap)
505 // Add 4 per row, and another numRows*4 for every 4 columns
506 // (col&0xFC==col/4*4), and then the column %4
507 combo=startCombo+4*row+(col&0xFC)*numRows+col%4;
508 else
509 combo++;
510
511 combobuf[combo]=combobuf[startCombo];
512 combobuf[combo].set_tile(tile);
513 }
514 }
515
516 setup_combo_animations();
517 setup_combo_animations2();
518 }
519
520 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t c);
521
522 static bool nogotiles = false;
523 static bool nogocombos = false;
524
525 void go_tiles()
526 {
527 if(nogotiles) return;
528 last_tile_move_list = nullopt;
529 for(int32_t i=0; i<NEWMAXTILES; ++i)
530 {
531 newundotilebuf[i].format=newtilebuf[i].format;
532
533 if(newundotilebuf[i].data!=NULL)
534 {
535 free(newundotilebuf[i].data);
536 }
537
538 newundotilebuf[i].data=(byte *)malloc(tilesize(newundotilebuf[i].format));
539
540 if(newundotilebuf[i].data==NULL)
541 {
542 Z_error_fatal("Unable to initialize undo tile #%ld.\n", i);
543 }
544
545 memcpy(newundotilebuf[i].data,newtilebuf[i].data,tilesize(newundotilebuf[i].format));
546 }
547 }
548
549 void go_slide_tiles(int32_t columns, int32_t rows, int32_t top, int32_t left)
550 {
551 for(int32_t c=0; c<columns; c++)
552 {
553 for(int32_t r=0; r<rows; r++)
554 {
555 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
556 newundotilebuf[t].format=newtilebuf[t].format;
557
558 if(newundotilebuf[t].data!=NULL)
559 {
560 free(newundotilebuf[t].data);
561 }
562
563 newundotilebuf[t].data=(byte *)malloc(tilesize(newundotilebuf[t].format));
564
565 if(newundotilebuf[t].data==NULL)
566 {
567 Z_error_fatal("Unable to initialize undo tile #%ld.\n", t);
568 }
569
570 memcpy(newundotilebuf[t].data,newtilebuf[t].data,tilesize(newundotilebuf[t].format));
571 }
572 }
573 }
574
575 void comeback_tiles()
576 {
577 if(last_tile_move_list)
578 {
579 last_tile_move_list->undo();
580 last_tile_move_list = nullopt;
581 }
582 for(dword i=0; i<NEWMAXTILES; ++i)
583 {
584 if(newtilebuf[i].format != newundotilebuf[i].format || !newtilebuf[i].data)
585 {
586 newtilebuf[i].format = newundotilebuf[i].format;
587
588 if(newtilebuf[i].data!=NULL)
589 free(newtilebuf[i].data);
590 newtilebuf[i].data=(byte *)malloc(tilesize(newtilebuf[i].format));
591 if(newtilebuf[i].data==NULL)
592 Z_error_fatal("Unable to initialize tile #%ld.\n", i);
593 }
594
595 memcpy(newtilebuf[i].data,newundotilebuf[i].data,tilesize(newtilebuf[i].format));
596 }
597
598 register_blank_tiles();
599 register_used_tiles();
600 }
601
602 void go_combos()
603 {
604 if(nogocombos) return;
605 last_combo_move_list = nullopt;
606
607 undocombobuf = combobuf;
608 }
609
610 void comeback_combos()
611 {
612 if(last_combo_move_list)
613 {
614 last_combo_move_list->undo();
615 last_combo_move_list = nullopt;
616 }
617
618 combobuf = undocombobuf;
619 }
620
621 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t s)
622 {
623 line(dest,x,y,x+s,y+s,c);
624 line(dest,x+s,y,x,y+s,c);
625 }
626 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t w, int32_t h)
627 {
628 line(dest,x,y,x+w,y+h,c);
629 line(dest,x+w,y,x,y+h,c);
630 }
631
632 enum {gm_light, gm_dark, gm_max};
633 int32_t gridmode=gm_light;
634
635 bool has_selection()
636 {
637 for(int32_t i=1; i<17; ++i)
638 {
639 for(int32_t j=1; j<17; ++j)
640 {
641 if(selection_grid[i][j])
642 {
643 return true;
644 }
645 }
646 }
647
648 return false;
649 }
650
651 void draw_selection_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
652 {
653 drawing_mode(DRAW_MODE_COPY_PATTERN, selection_pattern, selection_anchor>>3, 0);
654
655 for(int32_t i=1; i<18; ++i)
656 {
657 for(int32_t j=1; j<18; ++j)
658 {
659 // zoomtile16(screen2,tile,79,31,cs,flip,8);
660 if(selection_grid[i-1][j]!=selection_grid[i][j])
661 {
662 _allegro_vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
663 }
664
665 if(selection_grid[i][j-1]!=selection_grid[i][j])
666 {
667 _allegro_hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
668 }
669 }
670 }
671
672 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
673 // selection_anchor=(selection_anchor+1)%64;
674 }
675
676 bool is_selecting()
677 {
678 return (selecting_x1>-1&&selecting_x2>-1&&selecting_y1>-1&&selecting_y2>-1);
679 }
680
681 void draw_selecting_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
682 {
683 int32_t x1=zc_min(selecting_x1,selecting_x2);
684 int32_t x2=zc_max(selecting_x1,selecting_x2);
685 int32_t y1=zc_min(selecting_y1,selecting_y2);
686 int32_t y2=zc_max(selecting_y1,selecting_y2);
687
688 // rect(dest, x+(x1*scale2), y+(y1*scale2), x+((x2+1)*scale2), y+((y2+1)*scale2), 255);
689 for(int32_t i=1; i<18; ++i)
690 {
691 for(int32_t j=1; j<18; ++j)
692 {
693 drawing_mode(DRAW_MODE_COPY_PATTERN, selecting_pattern, selection_anchor>>3, 0);
694
695 if(((j>=y1+1)&&(j<=y2+1))&&((i==x1+1)||(i==x2+2)))
696 {
697 if(selection_grid[i-1][j]!=selection_grid[i][j])
698 {
699 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
700 }
701
702 _allegro_vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
703 }
704
705 if(((i>=x1+1)&&(i<=x2+1))&&((j==y1+1)||(j==y2+2)))
706 {
707 if(selection_grid[i][j-1]!=selection_grid[i][j])
708 {
709 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
710 }
711
712 _allegro_hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
713 }
714 }
715 }
716
717 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
718 // selection_anchor=(selection_anchor+1)%64;
719 }
720
721 void unfloat_selection();
722 bool floating_sel = false;
723 byte floatsel[256];
724 byte undofloatsel[256];
725 bool undo_is_floatsel = false;
726
727
728 void add_color_to_selection(int32_t color)
729 {
730 unfloat_selection();
731 for(int32_t i=1; i<17; ++i)
732 {
733 for(int32_t j=1; j<17; ++j)
734 {
735 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
736 {
737 selection_grid[i][j]=1;
738 }
739 }
740 }
741 }
742
743 void remove_color_from_selection(int32_t color)
744 {
745 unfloat_selection();
746 for(int32_t i=1; i<17; ++i)
747 {
748 for(int32_t j=1; j<17; ++j)
749 {
750 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
751 {
752 selection_grid[i][j]=0;
753 }
754 }
755 }
756 }
757
758 void intersect_color_with_selection(int32_t color)
759 {
760 unfloat_selection();
761 for(int32_t i=1; i<17; ++i)
762 {
763 for(int32_t j=1; j<17; ++j)
764 {
765 if((unpackbuf[((j-1)<<4)+(i-1)]==color)&&(selection_grid[i][j]==1))
766 {
767 selection_grid[i][j]=1;
768 }
769 else
770 {
771 selection_grid[i][j]=0;
772 }
773 }
774 }
775 }
776
777 bool is_in_selection(int32_t x, int32_t y)
778 {
779 x %= 16; y %= 16;
780 if(x < 0) x = (16 - abs(x));
781 if(y < 0) y = (16 - abs(y));
782 return (!has_selection()||(selection_grid[x+1][y+1]!=0));
783 }
784
785 void zoomtile16(BITMAP *dest,int32_t tile,int32_t x,int32_t y,int32_t cset,int32_t flip,int32_t m)
786 {
787 // rectfill(dest,x,y,x+(16*m),y+(16*m),gridmode==gm_light?jwin_pal[jcMEDLT]:jwin_pal[jcDARK]);
788 int gridcol = gridmode==gm_light?vc(7):vc(8);
789
790 cset <<= 4;
791 if(newtilebuf[tile].format>tf4Bit)
792 cset=0;
793
794 int g = hide_grid ? 1 : 0;
795 byte transp_col = (bgmode == BGMODE_TRANSP ? jwin_pal[jcBOX] : 0+cset);
796 rectfill(dest,x,y,x+(16*m)+g,y+(16*m)+g,transp_col);
797
798 unpack_tile(newtilebuf, tile, 0, false);
799 byte *si = unpackbuf;
800 for(int32_t cy=0; cy<16; cy++)
801 {
802 for(int32_t cx=0; cx<16; cx++)
803 {
804 byte col = (floating_sel && floatsel[cx+(cy<<4)]) ? floatsel[cx+(cy<<4)] : *si;
805 int32_t dx = ((flip&1)?15-cx:cx)*m;
806 int32_t dy = ((flip&2)?15-cy:cy)*m;
807 if(col)
808 rectfill(dest,x+dx,y+dy,x+dx+m-1,y+dy+m-1,col+cset);
809
810 if(!col && xmode == XMODE_X)
811 little_x(dest,x+dx+m/4,y+dy+m/4,invcol,m/2);
812
813 ++si;
814 }
815 }
816
817 if(!hide_grid)
818 {
819 for(int cx = 0; cx <= 16; ++cx)
820 _allegro_vline(dest,x+(cx*m),y,y+(16*m)-1,gridcol);
821 for(int cy = 0; cy <= 16; ++cy)
822 _allegro_hline(dest,x,y+(cy*m),x+(16*m)-1,gridcol);
823 }
824
825 if(show_quartgrid)
826 {
827 int offs = (8*m);
828 const int RAD = 3;
829 rectfill(dest,x+offs-RAD,y,x+offs+RAD,y+(16*m),gridcol);
830 rectfill(dest,x,y+offs-RAD,x+(16*m),y+offs+RAD,gridcol);
831 }
832
833 if(has_selection()||is_selecting())
834 {
835 selection_anchor=(selection_anchor+1)%64;
836
837 if(has_selection()||is_selecting())
838 draw_selection_outline(dest, x, y, m);
839
840 if(is_selecting())
841 draw_selecting_outline(dest, x, y, m);
842 }
843 }
844
845 void draw_text_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,int32_t flags,bool jwin)
846 {
847 if(!jwin)
848 {
849 if(flags&D_SELECTED)
850 {
851 zc_swap(fg,bg);
852 }
853
854 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
855 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
856 rect(dest,x,y,x+w-2,y+h-2,fg);
857 textout_centre_ex(dest,font,text,(x+x+w)>>1,((y+y+h)>>1)-4,fg,-1);
858 }
859 else
860 {
861 jwin_draw_text_button(dest, x, y, w, h, text, flags, true);
862 }
863 }
864
865 void draw_icon_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,int icon,int32_t bg,int32_t fg,int32_t flags,bool jwin)
866 {
867 if(!jwin)
868 {
869 if(flags&D_SELECTED)
870 {
871 zc_swap(fg,bg);
872 }
873
874 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
875 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
876 rect(dest,x,y,x+w-2,y+h-2,fg);
877 jwin_draw_icon(dest,x+w/2,y+h/2,fg,icon,icon_proportion(icon,w,h),true);
878 }
879 else
880 {
881 jwin_draw_icon_button(dest, x, y, w, h, icon, flags, true);
882 }
883 }
884
885 void draw_layer_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t flags)
886 {
887 if(flags&D_SELECTED)
888 {
889 rect(dest, x, y, x+w-1, y+h-1, jwin_pal[jcDARK]);
890 ++x;
891 ++y;
892 --w;
893 --h;
894 }
895 rectfill(dest,x+1,y+1,x+w-3,y+h-3,jwin_pal[(flags&D_SELECTED ? jcMEDDARK : jcBOX)]);
896 jwin_draw_frame(dest, x, y, w, h, (flags&D_SELECTED ? FR_DARK : FR_BOX));
897
898 //Forcibly fit the text within the button
899 char buf[512] = {0};
900 strcpy(buf, text);
901
902 bool dis = (flags&D_DISABLED);
903 auto hei = text_height(font);
904 auto len = text_length(font,buf);
905 auto borderwid = 8;
906 if(len > w - borderwid + (dis ? 1 : 0))
907 {
908 auto ind = strlen(buf) - 1;
909 auto dotcount = 0;
910 while(len > w - borderwid + (dis ? 1 : 0))
911 {
912 if(dotcount >= 2)
913 buf[ind+2] = 0;
914 else ++dotcount;
915 buf[ind--] = '.';
916 len = text_length(font,buf);
917 }
918 }
919 if(dis)
920 {
921 ++len; ++hei;
922 }
923 BITMAP* tmp = create_bitmap_ex(8,len,hei);
924 clear_bitmap(tmp);
925 if(dis)
926 {
927 textout_ex(tmp,font,buf,1,1,jwin_pal[jcLIGHT],-1);
928 textout_ex(tmp,font,buf,0,0,jwin_pal[jcDISABLED_FG],-1);
929 }
930 else
931 textout_ex(tmp,font,buf,0,0,jwin_pal[jcBOXFG],-1);
932 auto tx = x+((w-len)/2);
933 auto ty = y+((h-hei)/2);
934 if(len > w-borderwid)
935 {
936 tx = x+borderwid/2;
937 len = w-borderwid;
938 }
939 if(hei > h-borderwid)
940 {
941 ty = y+borderwid/2;
942 hei = h-borderwid;
943 }
944 masked_blit(tmp,dest, 0,0, tx,ty, len, hei);
945 destroy_bitmap(tmp);
946 }
947
948 bool do_layer_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text, int32_t flags, bool toggleflag)
949 {
950 bool over=false;
951
952 while(gui_mouse_b())
953 {
954 //vsync();
955 if(mouse_in_rect(x,y,w,h))
956 {
957 if(!over)
958 {
959 vsync();
960 draw_layer_button(screen, x, y, w, h, text, flags^D_SELECTED);
961 over=true;
962
963 update_hw_screen();
964 }
965 }
966 else
967 {
968 if(over)
969 {
970 vsync();
971 draw_layer_button(screen, x, y, w, h, text, flags);
972 over=false;
973
974 update_hw_screen();
975 }
976 }
977 rest(1);
978 }
979
980 if(over)
981 {
982 vsync();
983 draw_layer_button(screen, x, y, w, h, text, toggleflag ? flags^D_SELECTED : flags);
984
985 update_hw_screen();
986 }
987
988 return over;
989 }
990
991 bool do_text_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,bool jwin, bool sel)
992 {
993 bool over=false;
994
995 while(gui_mouse_b())
996 {
997 custom_vsync();
998
999 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1000 {
1001 if(!over)
1002 {
1003 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1004 over=true;
1005 }
1006 }
1007 else
1008 {
1009 if(over)
1010 {
1011 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?D_SELECTED:0,jwin);
1012 over=false;
1013 }
1014 }
1015 }
1016
1017 if(over)
1018 {
1019 custom_vsync();
1020 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1021 }
1022
1023 return over;
1024 }
1025
1026 void draw_graphics_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,int32_t flags,bool jwin,bool overlay)
1027 {
1028 if(!jwin)
1029 {
1030 if(flags&D_SELECTED)
1031 {
1032 zc_swap(fg,bg);
1033 }
1034
1035 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
1036 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
1037 rect(dest,x,y,x+w-2,y+h-2,fg);
1038 int32_t g = (flags & D_SELECTED) ? 1 : 0;
1039
1040 if(overlay)
1041 {
1042 masked_blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1043 }
1044 else
1045 {
1046 blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1047 }
1048 }
1049 else
1050 {
1051 jwin_draw_graphics_button(dest, x, y, w, h, bmp, bmp2, flags, false, overlay);
1052 }
1053 }
1054
1055 bool do_graphics_button(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1056 {
1057 bool over=false;
1058
1059 while(gui_mouse_b())
1060 {
1061 custom_vsync();
1062
1063 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1064 {
1065 if(!over)
1066 {
1067 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1068 over=true;
1069 }
1070 }
1071 else
1072 {
1073 if(over)
1074 {
1075 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1076 over=false;
1077 }
1078 }
1079 }
1080
1081 return over;
1082 }
1083
1084 bool do_graphics_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1085 {
1086 bool over=false;
1087
1088 while(gui_mouse_b())
1089 {
1090 custom_vsync();
1091
1092 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1093 {
1094 if(!over)
1095 {
1096 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1097 over=true;
1098 }
1099 }
1100 else
1101 {
1102 if(over)
1103 {
1104 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1105 over=false;
1106 }
1107 }
1108 }
1109
1110 if(over)
1111 {
1112 custom_vsync();
1113 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1114 }
1115
1116 return over;
1117 }
1118 // circle(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1119 // circlefill(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1120
1121 void draw_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg, int32_t value)
1122 {
1123 //these are here to bypass compiler warnings about unused arguments
1124 bg=bg;
1125 fg=fg;
1126
1127 int32_t r, center;
1128
1129 for(int32_t k=0; k<7; k++)
1130 {
1131 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1132 {
1133 // circle(dest, x+(k*25)+4, y+4, 4, fg);
1134 // circlefill(dest, x+(k*25)+4, y+4, 2, (value==k)?fg:bg);
1135 //*
1136 r = 9/2;
1137
1138 center = x+(k*25)+r;
1139 rectfill(dest, x+(k*25), y, x+(k*25)+9-1, y+9-1, jwin_pal[jcBOX]);
1140
1141 circlefill(dest, center, y+r, r, jwin_pal[jcLIGHT]);
1142 arc(dest, center, y+r, itofix(32), itofix(160), r, jwin_pal[jcMEDDARK]);
1143 circlefill(dest, center, y+r, r-1, jwin_pal[jcMEDLT]);
1144 arc(dest, center, y+r, itofix(32), itofix(160), r-1, jwin_pal[jcDARK]);
1145 circlefill(dest, center, y+r, r-2, jwin_pal[jcLIGHT]);
1146
1147 if(value==k)
1148 {
1149 circlefill(dest, center, y+r, r-3, jwin_pal[jcDARK]);
1150 }
1151
1152 //*/
1153 }
1154 }
1155 }
1156
1157 void do_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg,int32_t &value)
1158 {
1159 while(gui_mouse_b())
1160 {
1161 custom_vsync();
1162
1163 for(int32_t k=0; k<7; k++)
1164 {
1165 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1166 {
1167 //if on radio button
1168 if(isinRect(gui_mouse_x(),gui_mouse_y(),x+(k*25),y,x+(k*25)+8,y+8))
1169 {
1170 value=k;
1171 draw_layerradio(dest,x,y,bg,fg,value);
1172 refresh(rMENU);
1173 }
1174 }
1175 }
1176 }
1177 }
1178
1179 //*************** tile flood fill stuff **************
1180
1181 byte tf_c;
1182 byte tf_u;
1183
1184 void tile_floodfill_rec(int32_t x,int32_t y)
1185 {
1186 if(is_in_selection(x,y))
1187 {
1188 while(x>0 && (unpackbuf[(y<<4)+x-1] == tf_u))
1189 --x;
1190
1191 while(x<=15 && (unpackbuf[(y<<4)+x] == tf_u))
1192 {
1193 if(is_in_selection(x,y))
1194 {
1195 unpackbuf[(y<<4)+x] = tf_c;
1196 }
1197
1198 if(y>0 && (unpackbuf[((y-1)<<4)+x] == tf_u))
1199 tile_floodfill_rec(x,y-1);
1200
1201 if(y<15 && (unpackbuf[((y+1)<<4)+x] == tf_u))
1202 tile_floodfill_rec(x,y+1);
1203
1204 ++x;
1205 }
1206 }
1207 }
1208
1209 void tile_floodfill(int32_t tile,int32_t x,int32_t y,byte c)
1210 {
1211 if(is_in_selection(x,y))
1212 {
1213 if(floating_sel)
1214 {
1215 memcpy(unpackbuf, floatsel, 256);
1216 }
1217 else unpack_tile(newtilebuf, tile, 0, false);
1218 tf_c = c;
1219 tf_u = unpackbuf[(y<<4)+x];
1220
1221 if(tf_u != tf_c)
1222 tile_floodfill_rec(x,y);
1223 if(floating_sel)
1224 {
1225 memcpy(floatsel, unpackbuf, 256);
1226 }
1227 else pack_tile(newtilebuf,unpackbuf,tile);
1228 }
1229 }
1230
1231 //***************** tile editor stuff *****************
1232 8 size_and_pos ok_button(302,562,71,21);
1233 8 size_and_pos cancel_button(376,562,71,21);
1234 8 size_and_pos edit_button(550,562,86,21);
1235 8 size_and_pos hlcbox(742,392,16,16);
1236 8 size_and_pos hov_prev(742,338,50,50);
1237 8 size_and_pos cpalette_4(648,416,4,4,64,64);
1238 8 size_and_pos cpalette_8(648,416,16,14,16,18);
1239 8 size_and_pos fg_prev(648,316,50,50);
1240 8 size_and_pos bg_prev(648+30,316+30,50,50);
1241 8 size_and_pos zoomtile(124,32,16,16,32,32);
1242 8 size_and_pos prev_til_1(648,31,96,96);
1243 8 size_and_pos prev_til_2(752,31,96,96);
1244 8 size_and_pos prev_til_3(648,135,96,96);
1245 8 size_and_pos prev_til_4(752,135,96,96);
1246 8 size_and_pos status_info(648,308-(4*8),1,4,1,8);
1247 8 size_and_pos hover_info(742,338-(3*8),1,3,1,8);
1248 8 size_and_pos color_info(4,189,1,1,116,8);
1249 8 size_and_pos color_info_btn(24,189,96,21);
1250 8 size_and_pos tool_btns(22,29,2,4,39,39);
1251 8 size_and_pos x_btn(890,5,15,13);
1252 8 size_and_pos info_btn(872,5,15,13);
1253 8 size_and_pos hidegrid_cbox(124,552,16,16);
1254 8 size_and_pos quartgrid_cbox(124,572,16,16);
1255 8 size_and_pos reflbtn_grid(124,610,2,3,71,21);
1256 8 size_and_pos xmodebtn_grid(300,610,1,2,90,21);
1257 8 size_and_pos bgmodebtn_grid(390,610,1,2,90,21);
1258
1259 int32_t c1=1;
1260 int32_t c2=0;
1261 //int32_t bgc=dvc(4+5);
1262 //int32_t bgc=vc(1);
1263 //enum { t_pen, t_fill, t_recolor, t_eyedropper, t_move, t_select, t_wand, t_max };
1264 int32_t floating_tile = -1;
1265 int32_t tool = t_pen;
1266 int32_t old_tool = -1;
1267 int32_t tool_cur = -1;
1268 int32_t select_mode = 0;
1269 int32_t drawing=0;
1270
1271 bool qgrid_tool(int tool)
1272 {
1273 switch(tool)
1274 {
1275 case t_pen:
1276 case t_fill:
1277 case t_recolor:
1278 case t_wand:
1279 return true;
1280 }
1281 return false;
1282 }
1283
1284 void set_tool_sprite(int tool, int type)
1285 {
1286 int spr = ZQM_NORMAL;
1287 switch(tool)
1288 {
1289 case t_pen: spr = ZQM_SWORD; break;
1290 case t_fill: spr = ZQM_POTION; break;
1291 case t_recolor: spr = ZQM_WAND; break;
1292 case t_eyedropper: spr = ZQM_LENS; break;
1293 case t_move: spr = ZQM_GLOVE_OPEN+type; break;
1294 case t_select: spr = ZQM_HOOK_PLAIN+type; break;
1295 case t_wand: spr = ZQM_SEL_WAND_PLAIN+type; break;
1296 }
1297 MouseSprite::set(spr);
1298 }
1299 void update_tool_cursor()
1300 {
1301 // int32_t screen_xofs=(zq_screen_w-320)>>1;
1302 // int32_t screen_yofs=(zq_screen_h-240)>>1;
1303 // int32_t temp_mouse_x=gui_mouse_x()-screen_xofs;
1304 // int32_t temp_mouse_y=gui_mouse_y()-screen_yofs;
1305 int32_t temp_mouse_x=gui_mouse_x();
1306 int32_t temp_mouse_y=gui_mouse_y();
1307
1308 int32_t type=0;
1309
1310 if(has_selection())
1311 {
1312 switch(tool)
1313 {
1314 case t_select:
1315 case t_wand:
1316 type+=select_mode;
1317 break;
1318 }
1319 }
1320
1321 // if(isinRect(temp_mouse_x,temp_mouse_y,80,32,206,158)) //inside the zoomed tile window
1322 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
1323 {
1324 if(tool_cur==-1)
1325 set_tool_sprite(tool,type);
1326
1327 tool_cur=tool;
1328 }
1329 else if(tool_cur != -1)
1330 {
1331 MouseSprite::set(ZQM_NORMAL);
1332 tool_cur = -1;
1333 }
1334 }
1335
1336 void draw_edit_scr(int32_t tile,int32_t flip,int32_t cs,byte *oldtile, bool create_tbar)
1337 {
1338 PALETTE tpal;
1339 static BITMAP *tbar = create_bitmap_ex(8,zq_screen_w-6, 18);
1340 static BITMAP *preview_bmp = create_bitmap_ex(8, 64, 64);
1341 jwin_draw_win(screen2, 0, 0, zq_screen_w, zq_screen_h, FR_WIN);
1342
1343 if(!create_tbar)
1344 {
1345 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1346 }
1347 else
1348 {
1349 jwin_draw_titlebar(tbar, 0, 0, zq_screen_w-6, 18, "", true, true);
1350 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1351 }
1352
1353 textprintf_ex(screen2,get_zc_font(font_lfont),5,5,jwin_pal[jcTITLEFG],-1,"Tile Editor (%d)",tile);
1354
1355 clear_to_color(preview_bmp, 0);
1356
1357 zc_swap(oldtile,newtilebuf[tile].data); //Put oldtile in the tile buffer
1358 jwin_draw_win(screen2, prev_til_1.x-2,prev_til_1.y-2, prev_til_1.w+4, prev_til_1.h+4, FR_DEEP);
1359 puttile16(preview_bmp,tile,0,0,cs,flip);
1360 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_1.x, prev_til_1.y, prev_til_1.w, prev_til_1.h);
1361
1362 clear_to_color(preview_bmp, 0);
1363 jwin_draw_win(screen2, prev_til_2.x-2,prev_til_2.y-2, prev_til_2.w+4, prev_til_2.h+4, FR_DEEP);
1364 overtile16(preview_bmp,tile,0,0,cs,flip);
1365 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_2.x, prev_til_2.y, prev_til_2.w, prev_til_2.h);
1366 zc_swap(oldtile,newtilebuf[tile].data); //Swap the real tile back to the buffer
1367
1368 unpack_tile(newtilebuf, tile, 0, true);
1369 if(floating_sel)
1370 for(auto q = 0; q < 256; ++q)
1371 if(floatsel[q])
1372 unpackbuf[q] = floatsel[q];
1373 byte tmptile[256];
1374 byte *tmpptr = tmptile;
1375 zc_swap(tmpptr,newtilebuf[tile].data); //Put temp data in the tile buffer
1376 pack_tile(newtilebuf,unpackbuf,tile);
1377 clear_to_color(preview_bmp, 0);
1378
1379 jwin_draw_win(screen2, prev_til_3.x-2,prev_til_3.y-2, prev_til_3.w+4, prev_til_3.h+4, FR_DEEP);
1380 puttile16(preview_bmp,tile,0,0,cs,flip);
1381 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_3.x, prev_til_3.y, prev_til_3.w, prev_til_3.h);
1382
1383 clear_to_color(preview_bmp, 0);
1384 jwin_draw_win(screen2, prev_til_4.x-2,prev_til_4.y-2, prev_til_4.w+4, prev_til_4.h+4, FR_DEEP);
1385 overtile16(preview_bmp,tile,0,0,cs,flip);
1386 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_4.x, prev_til_4.y, prev_til_4.w, prev_til_4.h);
1387
1388 //Color info
1389 {
1390 auto fh = color_info.yscale = text_height(font);
1391 int y = color_info.y;
1392 int rx = color_info.x+color_info.xscale;
1393 color_info.h = 1;
1394 if(showcolortip)
1395 {
1396 gui_textout_ln(screen2,font,(unsigned char*)"Colors:",
1397 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1398 auto str = get_tile_colornames(tile,cs);
1399 size_t pos = 0;
1400 char buf[512] = {0};
1401 char cbuf[16] = {0};
1402 while(pos < str.size())
1403 {
1404 y += fh;
1405 if(y+fh > zq_screen_h)
1406 break; //Out of space!
1407 auto endpos = str.find_first_of('\n',pos);
1408
1409 if(endpos == std::string::npos)
1410 {
1411 strcpy(buf,str.substr(pos).c_str());
1412 pos = str.size();
1413 }
1414 else
1415 {
1416 strcpy(buf,str.substr(pos,endpos-pos+1).c_str());
1417 pos = endpos+1;
1418 }
1419 //Ensure the name fits horizontally
1420 if(text_length(font,buf) > color_info.xscale)
1421 {
1422 size_t pos = 0;
1423 for(; buf[pos]; ++pos)
1424 {
1425 if(buf[pos] == ':')
1426 {
1427 strcpy(cbuf, buf+pos);
1428 buf[pos] = 0;
1429 break;
1430 }
1431 }
1432 size_t clen = text_length(font,cbuf);
1433 size_t dotlen = text_length(font,"..");
1434
1435 while(pos > 0 && (dotlen+clen+text_length(font,buf) > color_info.xscale))
1436 buf[--pos] = 0;
1437 while(buf[pos] == ' ')
1438 buf[pos] = 0;
1439 strcat(buf,"..");
1440 strcat(buf,cbuf);
1441 }
1442 gui_textout_ln(screen2,font,(unsigned char const*)buf,
1443 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1444 ++color_info.h;
1445 }
1446 jwin_draw_frame(screen2,color_info.x-2,color_info.y-2,(color_info.w*color_info.xscale)+4,(color_info.h*color_info.yscale)+4,FR_DEEP);
1447 }
1448 else
1449 {
1450 draw_text_button(screen2,color_info_btn.x,color_info_btn.y,color_info_btn.w,color_info_btn.h,
1451 "Show Colors",vc(1),vc(14),0,true);
1452 }
1453 }
1454
1455 zc_swap(tmpptr,newtilebuf[tile].data); //Swap the real tile back to the buffer
1456
1457 jwin_draw_win(screen2, zoomtile.x-3, zoomtile.y-3, (zoomtile.w*zoomtile.xscale)+5, (zoomtile.h*zoomtile.yscale)+5, FR_DEEP);
1458 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
1459
1460 if(floating_sel)
1461 textprintf_ex(screen2,font,status_info.x,status_info.y+0,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Floating selection");
1462 textprintf_ex(screen2,font,status_info.x,status_info.y+(1*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile: %d",tile);
1463 if(newtilebuf[tile].format==tf8Bit)
1464 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"8-bit");
1465 else
1466 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cset: %d",cs);
1467
1468 PALETTE temppal;
1469
1470 //palette and mouse
1471 switch(newtilebuf[tile].format)
1472 {
1473 case tf4Bit:
1474 jwin_draw_win(screen2, cpalette_4.x-2, cpalette_4.y-2, (cpalette_4.xscale*cpalette_4.w)+4, (cpalette_4.yscale*cpalette_4.h)+4, FR_DEEP);
1475 get_palette(temppal);
1476
1477 for(int32_t i=0; i<cpalette_4.w*cpalette_4.h; i++)
1478 {
1479 size_and_pos const& s = cpalette_4.subsquare(i);
1480 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,CSET(cs)+i);
1481 }
1482
1483 little_x(screen2,cpalette_4.x+1,cpalette_4.y+1,invcol,cpalette_4.xscale-5,cpalette_4.yscale-5);
1484 break;
1485
1486 case tf8Bit:
1487 jwin_draw_win(screen2, cpalette_8.x-2, cpalette_8.y-2, (cpalette_8.xscale*cpalette_8.w)+4, (cpalette_8.yscale*cpalette_8.h)+4, FR_DEEP);
1488
1489 for(int32_t i=0; i<cpalette_8.w*cpalette_8.h; ++i)
1490 {
1491 size_and_pos const& s = cpalette_8.subsquare(i);
1492 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,i);
1493 }
1494
1495 little_x(screen2,cpalette_8.x+1,cpalette_8.y+1,invcol,cpalette_8.xscale-5,cpalette_8.yscale-5);
1496 break;
1497 }
1498
1499 rect(screen2, bg_prev.x, bg_prev.y, bg_prev.x+bg_prev.w-1, bg_prev.y+bg_prev.h-1, jwin_pal[jcTEXTFG]);
1500 rectfill(screen2, bg_prev.x+1, bg_prev.y+1, bg_prev.x+bg_prev.w-2, bg_prev.y+bg_prev.h-2, jwin_pal[jcTEXTBG]);
1501 rectfill(screen2, bg_prev.x+3, bg_prev.y+3, bg_prev.x+bg_prev.w-4, bg_prev.y+bg_prev.h-4, c2+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1502
1503 if(c2==0)
1504 {
1505 little_x(screen2, bg_prev.x+1, bg_prev.y+1, invcol, bg_prev.w-2, bg_prev.h-2);
1506 }
1507
1508 rect(screen2, fg_prev.x, fg_prev.y, fg_prev.x+fg_prev.w-1, fg_prev.y+fg_prev.h-1, jwin_pal[jcTEXTFG]);
1509 rectfill(screen2, fg_prev.x+1, fg_prev.y+1, fg_prev.x+fg_prev.w-2, fg_prev.y+fg_prev.h-2, jwin_pal[jcTEXTBG]);
1510 rectfill(screen2, fg_prev.x+3, fg_prev.y+3, fg_prev.x+fg_prev.w-4, fg_prev.y+fg_prev.h-4, c1+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1511
1512 if(c1==0)
1513 {
1514 little_x(screen2, fg_prev.x+1, fg_prev.y+1, invcol, fg_prev.w-2, fg_prev.h-2);
1515 }
1516
1517 draw_text_button(screen2,ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK",vc(1),vc(14),0,true);
1518 draw_text_button(screen2,cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel",vc(1),vc(14),0,true);
1519 draw_text_button(screen2,edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal",vc(1),vc(14),0,true);
1520 draw_checkbox(screen2,hlcbox.x, hlcbox.y, hlcbox.w, hlcbox.h, tthighlight);
1521 gui_textout_ln(screen2,font,(unsigned char*)"Highlight Hover",hlcbox.x+hlcbox.w+2,hlcbox.y+hlcbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1522
1523 draw_checkbox(screen2,quartgrid_cbox.x, quartgrid_cbox.y, quartgrid_cbox.w, quartgrid_cbox.h, show_quartgrid);
1524 gui_textout_ln(screen2,font,(unsigned char*)"Quarter Grid",quartgrid_cbox.x+quartgrid_cbox.w+2,quartgrid_cbox.y+quartgrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1525
1526 draw_checkbox(screen2,hidegrid_cbox.x, hidegrid_cbox.y, hidegrid_cbox.w, hidegrid_cbox.h, hide_grid);
1527 gui_textout_ln(screen2,font,(unsigned char*)"Hide Grid",hidegrid_cbox.x+hidegrid_cbox.w+2,hidegrid_cbox.y+hidegrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1528
1529 bool qgrd = show_quartgrid && qgrid_tool(tool);
1530 gui_textout_ln(screen2,font,(unsigned char*)"Quarter-Grid Draw Modes", reflbtn_grid.x, reflbtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],qgrd?0:D_DISABLED);
1531 for(int q = 0; q < REFL_MAX; ++q)
1532 {
1533 auto& sqr = reflbtn_grid.subsquare(q);
1534 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[q],vc(1),vc(14),qgrd ? ((refl_flags&(1<<q)) ? D_SELECTED : 0) : D_DISABLED,true);
1535 }
1536 gui_textout_ln(screen2,font,(unsigned char*)"Transparent Mode", xmodebtn_grid.x, xmodebtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1537 for(int q = 0; q < XMODE_MAX; ++q)
1538 {
1539 auto& sqr = xmodebtn_grid.subsquare(q);
1540 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[q],vc(1),vc(14),(xmode == q) ? D_SELECTED : 0,true);
1541 }
1542 for(int q = 0; q < BGMODE_MAX; ++q)
1543 {
1544 auto& sqr = bgmodebtn_grid.subsquare(q);
1545 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[q],vc(1),vc(14),(bgmode == q) ? D_SELECTED : 0,true);
1546 }
1547
1548 //tool buttons
1549 for(int32_t toolbtn = 0; toolbtn < t_max; ++toolbtn)
1550 {
1551 auto bmp = toolbtn+MOUSE_BMP_SWORD;
1552 int col = toolbtn%tool_btns.w;
1553 int row = toolbtn/tool_btns.w;
1554
1555 jwin_draw_button(screen2,tool_btns.x+(col*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale,tool==toolbtn?2:0,0);
1556 masked_stretch_blit(mouse_bmp_1x[bmp][0],screen2,0,0,16,16,tool_btns.x+(col*tool_btns.xscale)+3+(tool==toolbtn?1:0),tool_btns.y+3+(row*tool_btns.yscale)+(tool==toolbtn?1:0),tool_btns.xscale-7,tool_btns.yscale-7);
1557 }
1558
1559 //coordinates
1560 {
1561 auto mx = gui_mouse_x();
1562 auto my = gui_mouse_y();
1563 int32_t ind = zoomtile.rectind(mx,my);
1564 int32_t temp_x=ind%zoomtile.w;
1565 int32_t temp_y=ind/zoomtile.w;
1566 int color = -1;
1567
1568 bool is8b = newtilebuf[tile].format > tf4Bit;
1569 if(ind > -1)
1570 {
1571 char xbuf[16];
1572 sprintf(xbuf, "x: %d", temp_x);
1573 textprintf_ex(screen2,font,status_info.x,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%s",xbuf);
1574 textprintf_ex(screen2,font,status_info.x+text_length(font,xbuf)+8,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"y: %d",temp_y);
1575 unpack_tile(newtilebuf, tile, 0, false);
1576 byte *si = unpackbuf;
1577 si+=ind;
1578 color = *si;
1579 }
1580 else if(fg_prev.rect(mx,my))
1581 color = c1;
1582 else if(bg_prev.rect(mx,my))
1583 color = c2;
1584 else color = (is8b ? cpalette_8 : cpalette_4).rectind(mx,my);
1585 if(color > -1)
1586 {
1587 get_palette(tpal);
1588 char separator = ' ';
1589 char buf[512] = {0};
1590
1591 int realcol = color+(is8b?0:CSET(cs));
1592 bool xcolor = (is8b ? realcol == 0 : (realcol%16)==0);
1593 auto& c = tpal[realcol];
1594
1595 if(tthighlight)
1596 {
1597 size_and_pos const& mainsqr = is8b ? cpalette_8 : cpalette_4;
1598 size_and_pos const& csqr = mainsqr.subsquare(color);
1599
1600 int hlcol = getHighlightColor(tpal[realcol]);
1601 int hlthick = 4;
1602 int extraborder = is8b ? 8 : 0;
1603 int borderthick = hlthick+extraborder;
1604
1605 if(is8b)
1606 {
1607 highlight_sqr(screen2, 0xED, csqr.x, mainsqr.y, csqr.w, mainsqr.h*mainsqr.yscale, hlthick); //column
1608 highlight_sqr(screen2, 0xED, mainsqr.x, csqr.y, mainsqr.w*mainsqr.xscale, csqr.h, hlthick); //row
1609 }
1610 highlight_sqr(screen2, 0xED, csqr.x-borderthick, csqr.y-borderthick, csqr.w+borderthick*2, csqr.h+borderthick*2, hlthick); //square hl
1611 rectfill(screen2, csqr.x-extraborder, csqr.y-extraborder, csqr.x+csqr.w-1+extraborder, csqr.y+csqr.h-1+extraborder, realcol); //square color
1612 if(xcolor)
1613 little_x(screen2, csqr.x-extraborder+4, csqr.y-extraborder+4, invcol, csqr.w+(extraborder*2)-8, csqr.h+(extraborder*2)-8); //transparent X
1614 highlight_sqr(screen2, hlcol, csqr.x-extraborder, csqr.y-extraborder, csqr.w+extraborder*2, csqr.h+extraborder*2, 1); //highlight border
1615 }
1616
1617 sprintf(buf, "%02d %02d %02d %c(0x%02X %d)",c.r,c.g,c.b,separator,realcol,color);
1618 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(2*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1619
1620 strcpy(buf, get_color_name(realcol, is8b).c_str());
1621 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(1*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1622
1623 sprintf(buf, "#%02X%02X%02X", tpal[realcol].r*4,tpal[realcol].g*4,tpal[realcol].b*4);
1624 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(0),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1625
1626 rect(screen2, hov_prev.x, hov_prev.y, hov_prev.x+hov_prev.w-1, hov_prev.y+hov_prev.h-1, jwin_pal[jcTEXTFG]);
1627 rectfill(screen2, hov_prev.x+1, hov_prev.y+1, hov_prev.x+hov_prev.w-2, hov_prev.y+hov_prev.h-2, jwin_pal[jcTEXTBG]);
1628 rectfill(screen2, hov_prev.x+3, hov_prev.y+3, hov_prev.x+hov_prev.w-4, hov_prev.y+hov_prev.h-4, realcol);
1629 if(xcolor)
1630 little_x(screen2, hov_prev.x+1, hov_prev.y+1, invcol, hov_prev.w-2, hov_prev.h-2);
1631 }
1632 }
1633
1634 custom_vsync();
1635 blit(screen2,screen,0,0,0,0,zq_screen_w,zq_screen_w);
1636 update_tool_cursor();
1637 SCRFIX();
1638 }
1639
1640 void normalize(int32_t tile,int32_t tile2, bool rect_sel, int32_t flip)
1641 {
1642 unfloat_selection();
1643 if(tile>tile2)
1644 {
1645 zc_swap(tile, tile2);
1646 }
1647
1648 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
1649 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
1650
1651 int32_t start=tile;
1652 int32_t end=tile2;
1653
1654 // Might have top-right and bottom-left corners selected...
1655 if(rect_sel && TILECOL(tile)>TILECOL(tile2))
1656 {
1657 start=tile-(TILECOL(tile)-TILECOL(tile2));
1658 end=tile2+(TILECOL(tile)-TILECOL(tile2));
1659 }
1660
1661 for(int32_t temptile=start; temptile<=end; temptile++)
1662 {
1663 if(!rect_sel || ((TILECOL(temptile)>=left) && (TILECOL(temptile)<=left+columns-1)))
1664 {
1665 unpack_tile(newtilebuf, temptile, 0, true);
1666
1667 if(flip&1)
1668 {
1669 for(int32_t y=0; y<16; y++)
1670 {
1671 for(int32_t x=0; x<8; x++)
1672 {
1673 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[(y<<4)+15-x]);
1674 }
1675 }
1676 }
1677
1678 if(flip&2)
1679 {
1680 for(int32_t y=0; y<8; y++)
1681 {
1682 for(int32_t x=0; x<16; x++)
1683 {
1684 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[((15-y)<<4)+x]);
1685 }
1686 }
1687 }
1688
1689 pack_tile(newtilebuf,unpackbuf,temptile);
1690 }
1691 }
1692 }
1693
1694 void rotate_tile(int32_t tile, bool backward)
1695 {
1696 unfloat_selection();
1697 unpack_tile(newtilebuf, tile, 0, true);
1698 byte tempunpackbuf[256];
1699 byte tempx, tempy;
1700
1701 for(tempx=0; tempx<16; tempx++)
1702 {
1703 for(tempy=0; tempy<16; tempy++)
1704 {
1705 if(!backward)
1706 {
1707 tempunpackbuf[(tempy<<4)+tempx]=unpackbuf[((15-tempx)<<4)+tempy];
1708 }
1709 else
1710 {
1711 tempunpackbuf[((15-tempx)<<4)+tempy]=unpackbuf[(tempy<<4)+tempx];
1712 }
1713 }
1714 }
1715
1716 pack_tile(newtilebuf,tempunpackbuf,tile);
1717 }
1718
1719 static int32_t undocount=128;
1720 byte undotile[256];
1721
1722 void wrap_tile(int32_t tile, int32_t vertical, int32_t horizontal, bool clear)
1723 {
1724 byte buf[256];
1725
1726 for(int32_t i=0; i<undocount; i++)
1727 {
1728 newtilebuf[tile].data[i]=undotile[i];
1729 }
1730
1731 if(!(horizontal||vertical))
1732 {
1733 return;
1734 }
1735
1736 unpack_tile(newtilebuf, tile, 0, true);
1737
1738 for(int32_t i=0; i<256; i++)
1739 {
1740 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1741 buf[shift_ind] = unpackbuf[i];
1742 }
1743
1744 if(clear)
1745 {
1746 for(int32_t r=0; r<abs(vertical); r++)
1747 {
1748 for(int32_t c=0; c<16; c++)
1749 {
1750 buf[(vertical>0?r:15-r)*16+c]=0;
1751 }
1752 }
1753
1754 for(int32_t r=0; r<16; r++)
1755 {
1756 for(int32_t c=0; c<abs(horizontal); c++)
1757 {
1758 buf[r*16+(horizontal>0?c:15-c)]=0;
1759 }
1760 }
1761 }
1762
1763 pack_tile(newtilebuf,buf,tile);
1764 }
1765
1766 void wrap_sel_tile(int32_t vertical, int32_t horizontal)
1767 {
1768 byte buf[256];
1769
1770 if(!(horizontal||vertical))
1771 {
1772 return;
1773 }
1774
1775 memset(buf,0,256);
1776
1777 for(int32_t i=0; i<256; i++)
1778 {
1779 if(is_in_selection(i%16,i/16))
1780 {
1781 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1782 buf[shift_ind] = floatsel[i];
1783 }
1784 }
1785
1786 memcpy(floatsel,buf,256);
1787 }
1788
1789 void float_selection(int32_t tile, bool clear)
1790 {
1791 if(floating_sel) return;
1792 floating_sel = true;
1793 floating_tile = tile;
1794
1795 unpack_tile(newtilebuf, tile, 0, true);
1796
1797 for(auto q = 0; q < 256; ++q)
1798 {
1799 if(is_in_selection(q%16,q/16))
1800 {
1801 floatsel[q] = unpackbuf[q];
1802 unpackbuf[q] = clear ? 0 : c2;
1803 }
1804 else floatsel[q] = 0;
1805 }
1806
1807 pack_tile(newtilebuf,unpackbuf,tile);
1808 }
1809
1810 void unfloat_selection()
1811 {
1812 if(!floating_sel) return;
1813 floating_sel = false;
1814
1815 unpack_tile(newtilebuf, floating_tile, 0, true);
1816
1817 for(auto q = 0; q < 256; ++q)
1818 {
1819 if(floatsel[q])
1820 {
1821 unpackbuf[q] = floatsel[q];
1822 }
1823 }
1824
1825 pack_tile(newtilebuf,unpackbuf,floating_tile);
1826 floating_tile = -1;
1827 }
1828
1829 void shift_tile_colors(int32_t tile, int32_t amount, bool ignore_transparent)
1830 {
1831 if(floating_sel)
1832 {
1833 for(auto q = 0; q < 256; ++q)
1834 {
1835 if(ignore_transparent && floatsel[q]==0)
1836 continue;
1837 floatsel[q]=wrap(floatsel[q]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1838 }
1839 return;
1840 }
1841
1842 byte buf[256];
1843 unpack_tile(newtilebuf, tile, 0, true);
1844
1845 for(int32_t i=0; i<256; i++)
1846 {
1847 buf[i]=unpackbuf[i];
1848
1849 if(!is_in_selection(i&0x0F, (i&0xF0)>>4))
1850 continue;
1851
1852 if(ignore_transparent)
1853 {
1854 if(buf[i]==0)
1855 continue;
1856
1857 buf[i]=wrap(buf[i]+amount, 1, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1858 }
1859 else // Don't ignore transparent
1860 buf[i]=wrap(buf[i]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1861 }
1862
1863 pack_tile(newtilebuf,buf,tile);
1864 }
1865
1866 void clear_selection_grid()
1867 {
1868 unfloat_selection();
1869 for(int32_t x=0; x<18; ++x)
1870 {
1871 for(int32_t y=0; y<18; ++y)
1872 {
1873 selection_grid[x][y]=0;
1874 }
1875 }
1876 }
1877
1878 void invert_selection_grid()
1879 {
1880 unfloat_selection();
1881 for(int32_t x=1; x<17; ++x)
1882 {
1883 for(int32_t y=1; y<17; ++y)
1884 {
1885 selection_grid[x][y]=selection_grid[x][y]?0:1;
1886 }
1887 }
1888 }
1889
1890 void shift_selection_grid(int32_t xoffs, int32_t yoffs)
1891 {
1892 byte local_grid[16][16];
1893 memset(local_grid, 0, sizeof(local_grid));
1894 for(auto x = 0; x < 16; ++x)
1895 {
1896 for(auto y = 0; y < 16; ++y)
1897 {
1898 auto offs_x = (x+xoffs)%16, offs_y = (y+yoffs)%16;
1899 if(offs_x < 0) offs_x = (16 - abs(offs_x));
1900 if(offs_y < 0) offs_y = (16 - abs(offs_y));
1901 local_grid[offs_x][offs_y] = selection_grid[x+1][y+1]?1:0;
1902 }
1903 }
1904 for(auto x = 0; x < 16; ++x)
1905 {
1906 for(auto y = 0; y < 16; ++y)
1907 {
1908 selection_grid[x+1][y+1] = local_grid[x][y]?1:0;
1909 }
1910 }
1911 }
1912
1913 void show_edit_tile_help()
1914 {
1915 InfoDialog("Help: Tile Editor", "Hotkeys:"
1916 "\nF1: This Help Dialog"
1917 "\nEnter: Unfloat Sel / OK | Esc: Unfloat Sel / Cancel"
1918 "\nDelete: Clear Tile/Sel | Ctrl+Delete: Clear Tile"
1919 "\nA: Sel All | D: Unselect Sel | I: Invert Sel"
1920 "\nH/V: Flip | (Shift+)R: Rotate"
1921 "\n+/-: Change CSet | Ctrl +/-: Shift Colors"
1922 "\n(Ctrl+)S: Swap Colors | U/Ctrl+Z: Undo"
1923 "\nF12: Screenshot (whole screen)"
1924 "\nArrows: Shift Pixel | Ctrl+Arrows: Change Tile"
1925 "\nWhen not on Select tools, hold to swap:"
1926 "\nCtrl - Fill | Alt - Grab | Ctrl+Alt - Recolor").show();
1927 }
1928
1929 static int move_origin_x=-1, move_origin_y=-1;
1930 static int prev_x=-1, prev_y=-1;
1931 bool __pixel_draw(int x, int y, int tile, int flip)
1932 {
1933 bool ret = false;
1934 switch(tool)
1935 {
1936 case t_pen:
1937 if(flip&1) x=15-x;
1938
1939 if(flip&2) y=15-y;
1940
1941 if(is_in_selection(x,y))
1942 {
1943 if(floating_sel)
1944 {
1945 floatsel[(y<<4)+x]=(drawing==1)?c1:c2;
1946 }
1947 else
1948 {
1949 unpack_tile(newtilebuf, tile, 0, false);
1950 unpackbuf[((y<<4)+x)]=(drawing==1)?c1:c2;
1951 pack_tile(newtilebuf, unpackbuf,tile);
1952 }
1953 }
1954 break;
1955
1956 case t_fill:
1957 if(is_in_selection(x,y))
1958 {
1959 tile_floodfill(tile,x,y,(drawing==1)?c1:c2);
1960 ret = true;
1961 }
1962 break;
1963
1964 case t_recolor:
1965 if(is_in_selection(x,y))
1966 {
1967 if(floating_sel)
1968 {
1969 tf_u = floatsel[(y<<4)+x];
1970 for(int32_t i=0; i<256; i++)
1971 {
1972 if(is_in_selection(i&15,i>>4))
1973 {
1974 if(floatsel[i]==tf_u)
1975 {
1976 floatsel[i]=(drawing==1)?c1:c2;
1977 }
1978 }
1979 }
1980 }
1981 else
1982 {
1983 unpack_tile(newtilebuf, tile, 0, false);
1984 tf_u = unpackbuf[(y<<4)+x];
1985 if(tf_u != ((drawing==1)?c1:c2))
1986 {
1987 for(int32_t i=0; i<256; i++)
1988 {
1989 if(is_in_selection(i&15,i>>4))
1990 {
1991 if(unpackbuf[i]==tf_u)
1992 {
1993 unpackbuf[i]=(drawing==1)?c1:c2;
1994 }
1995 }
1996 }
1997
1998 pack_tile(newtilebuf, unpackbuf,tile);
1999 }
2000 }
2001 ret = true;
2002 }
2003 break;
2004
2005 case t_eyedropper:
2006 if(floating_sel)
2007 memcpy(unpackbuf, floatsel, 256);
2008 else unpack_tile(newtilebuf, tile, 0, false);
2009
2010 if(gui_mouse_b()&1)
2011 {
2012 c1=unpackbuf[((y<<4)+x)];
2013 }
2014
2015 if(gui_mouse_b()&2)
2016 {
2017 c2=unpackbuf[((y<<4)+x)];
2018 }
2019 break;
2020
2021 case t_move:
2022 if((prev_x!=x)||(prev_y!=y))
2023 {
2024 if(has_selection())
2025 {
2026 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2027 wrap_sel_tile(y-prev_y, x-prev_x);
2028 shift_selection_grid(x-prev_x, y-prev_y);
2029 }
2030 else wrap_tile(tile, y-move_origin_y, x-move_origin_x, drawing==2);
2031 prev_x=x;
2032 prev_y=y;
2033 }
2034 break;
2035
2036 case t_select:
2037 unfloat_selection();
2038 if(flip&1) x=15-x;
2039
2040 if(flip&2) y=15-y;
2041
2042 if(selecting_x1==-1||selecting_y1==-1)
2043 {
2044 selecting_x1=x;
2045 selecting_y1=y;
2046 }
2047 else
2048 {
2049 selecting_x2=x;
2050 selecting_y2=y;
2051 }
2052 break;
2053
2054 case t_wand:
2055 unfloat_selection();
2056 if(flip&1) x=15-x;
2057
2058 if(flip&2) y=15-y;
2059
2060 switch(select_mode)
2061 {
2062 case 0:
2063 clear_selection_grid();
2064 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2065 break;
2066
2067 case 1:
2068 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2069 break;
2070
2071 case 2:
2072 remove_color_from_selection(unpackbuf[((y<<4)+x)]);
2073 break;
2074
2075 case 3:
2076 intersect_color_with_selection(unpackbuf[((y<<4)+x)]);
2077 break;
2078 }
2079
2080 ret = true;
2081 break;
2082 }
2083 return ret;
2084 }
2085 void edit_tile(int32_t tile,int32_t flip,int32_t &cs)
2086 {
2087 popup_zqdialog_start();
2088 FONT* oldfont = font;
2089 font = get_custom_font(CFONT_DLG);
2090 edit_button.h = ok_button.h = cancel_button.h = 12+text_height(font);
2091 status_info.yscale = text_height(font);
2092 status_info.y = 308-(status_info.h*status_info.yscale);
2093 hover_info.yscale = status_info.yscale;
2094 hover_info.y = 338-(hover_info.h*hover_info.yscale);
2095 go();
2096 undocount = tilesize(newtilebuf[tile].format);
2097 clear_selection_grid();
2098 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2099
2100 tthighlight = zc_get_config("ZQ_GUI","tile_edit_fancyhighlight",1);
2101 showcolortip = zc_get_config("ZQ_GUI","tile_edit_colornames",1);
2102
2103 PALETTE tpal;
2104 byte oldtile[256];
2105
2106 memset(&tpal, 0, sizeof(PALETTE));
2107 memset(oldtile, 0, 256);
2108
2109 for(int32_t i=0; i<undocount; i++)
2110 {
2111 oldtile[i]=undotile[i]=newtilebuf[tile].data[i];
2112 }
2113 byte undoselgrid[16][16];
2114 for(auto x = 0; x < 16; ++x)
2115 for(auto y = 0; y < 16; ++y)
2116 undoselgrid[x][y] = selection_grid[x+1][y+1];
2117 for(auto q = 0; q < 256; ++q)
2118 {
2119 floatsel[q] = 0;
2120 undofloatsel[q] = 0;
2121 floating_sel = false;
2122 undo_is_floatsel = false;
2123 }
2124
2125 int32_t tile_x=-1, tile_y=-1;
2126 int32_t temp_x=-1, temp_y=-1;
2127 bool bdown=false;
2128 int32_t done=0;
2129 drawing=0;
2130 tool_cur = -1;
2131
2132 get_palette(tpal);
2133
2134 if(newtilebuf[tile].format==tf4Bit)
2135 {
2136 invcol=makecol8((63-tpal[CSET(cs)].r)*255/63,(63-tpal[CSET(cs)].g)*255/63,(63-tpal[CSET(cs)].b)*255/63);
2137 }
2138 else
2139 {
2140 invcol=makecol8((63-tpal[0].r)*255/63,(63-tpal[0].g)*255/63,(63-tpal[0].b)*255/63);
2141 }
2142
2143 custom_vsync();
2144 zc_set_palette(tpal);
2145 draw_edit_scr(tile,flip,cs,oldtile, true);
2146
2147 while(gui_mouse_b())
2148 {
2149 /* do nothing */
2150 rest(1);
2151 }
2152
2153 move_origin_x=-1;
2154 move_origin_y=-1;
2155 prev_x=-1;
2156 prev_y=-1;
2157
2158
2159
2160 byte selection_pattern_source[8][8]=
2161 {
2162 {1, 1, 1, 1, 0, 0, 0, 0},
2163 {1, 1, 1, 0, 0, 0, 0, 1},
2164 {1, 1, 0, 0, 0, 0, 1, 1},
2165 {1, 0, 0, 0, 0, 1, 1, 1},
2166 {0, 0, 0, 0, 1, 1, 1, 1},
2167 {0, 0, 0, 1, 1, 1, 1, 0},
2168 {0, 0, 1, 1, 1, 1, 0, 0},
2169 {0, 1, 1, 1, 1, 0, 0, 0},
2170 };
2171
2172 byte selecting_pattern_source[8][8]=
2173 {
2174 {1, 1, 0, 0, 0, 0, 1, 1},
2175 {1, 0, 0, 0, 0, 1, 1, 1},
2176 {0, 0, 0, 0, 1, 1, 1, 1},
2177 {0, 0, 0, 1, 1, 1, 1, 0},
2178 {0, 0, 1, 1, 1, 1, 0, 0},
2179 {0, 1, 1, 1, 1, 0, 0, 0},
2180 {1, 1, 1, 1, 0, 0, 0, 0},
2181 {1, 1, 1, 0, 0, 0, 0, 1},
2182 };
2183
2184 byte intersection_pattern_source[8][8]=
2185 {
2186 {0, 0, 1, 1, 0, 0, 1, 1},
2187 {0, 1, 1, 0, 0, 1, 1, 0},
2188 {1, 1, 0, 0, 1, 1, 0, 0},
2189 {1, 0, 0, 1, 1, 0, 0, 1},
2190 {0, 0, 1, 1, 0, 0, 1, 1},
2191 {0, 1, 1, 0, 0, 1, 1, 0},
2192 {1, 1, 0, 0, 1, 1, 0, 0},
2193 {1, 0, 0, 1, 1, 0, 0, 1},
2194 };
2195
2196 selection_pattern=create_bitmap_ex(8, 8, 8);
2197
2198 for(int32_t x=0; x<8; ++x)
2199 {
2200 for(int32_t y=0; y<8; ++y)
2201 {
2202 selection_pattern->line[y][x]=selection_pattern_source[x][y]?vc(0):vc(15);
2203 }
2204 }
2205
2206 selecting_pattern=create_bitmap_ex(8, 8, 8);
2207
2208 for(int32_t x=0; x<8; ++x)
2209 {
2210 for(int32_t y=0; y<8; ++y)
2211 {
2212 selecting_pattern->line[y][x]=selecting_pattern_source[x][y]?vc(0):vc(15);
2213 }
2214 }
2215
2216 intersection_pattern=create_bitmap_ex(8, 8, 8);
2217
2218 for(int32_t x=0; x<8; ++x)
2219 {
2220 for(int32_t y=0; y<8; ++y)
2221 {
2222 intersection_pattern->line[y][x]=intersection_pattern_source[x][y]?vc(0):vc(15);
2223 }
2224 }
2225
2226 do
2227 {
2228 HANDLE_CLOSE_ZQDLG();
2229 if(exiting_program) break;
2230 int32_t temp_mouse_x=gui_mouse_x();
2231 int32_t temp_mouse_y=gui_mouse_y();
2232 rest(4);
2233 bool redraw=false;
2234 bool did_wand_select=false;
2235
2236 if(keypressed())
2237 {
2238 bool ctrl = CHECK_CTRL_CMD;
2239 int k = readkey()>>8;
2240 switch(k)
2241 {
2242 case KEY_F1:
2243 show_edit_tile_help();
2244 break;
2245 case KEY_ENTER_PAD:
2246 case KEY_ENTER:
2247 if(floating_sel)
2248 unfloat_selection();
2249 else done=2;
2250 break;
2251
2252 case KEY_ESC:
2253 if(floating_sel)
2254 unfloat_selection();
2255 else if(has_selection())
2256 clear_selection_grid();
2257 else done=1;
2258 break;
2259
2260 case KEY_DEL:
2261 {
2262 unpack_tile(newtilebuf, tile, 0, false);
2263 bool all = CHECK_CTRL_CMD || !has_selection();
2264 bool canDel = false;
2265 if(all)
2266 {
2267 //Check all
2268 for(auto q = 0; q < 256; ++q)
2269 if(unpackbuf[q])
2270 {
2271 canDel = true;
2272 break;
2273 }
2274 }
2275 else
2276 {
2277 //Check selection
2278 for(auto x = 0; x < 16; ++x)
2279 for(auto y = 0; y < 16; ++y)
2280 if(is_in_selection(x,y))
2281 if(unpackbuf[(y<<4)+x])
2282 {
2283 canDel = true;
2284 break;
2285 }
2286 }
2287 if(!canDel) break; //don't delete (and thus reset undo) if nothing would change!
2288
2289 for(int32_t i=0; i<undocount; i++)
2290 {
2291 undotile[i]=newtilebuf[tile].data[i];
2292 }
2293 for(auto x = 0; x < 16; ++x)
2294 for(auto y = 0; y < 16; ++y)
2295 undoselgrid[x][y] = selection_grid[x+1][y+1];
2296 for(auto q = 0; q < 256; ++q)
2297 undofloatsel[q] = floatsel[q];
2298 undo_is_floatsel = floating_sel;
2299
2300 if(CHECK_CTRL_CMD || !has_selection())
2301 {
2302 //Delete all
2303 for(auto q = 0; q < 256; ++q)
2304 {
2305 unpackbuf[q] = 0;
2306 floatsel[q] = 0;
2307 }
2308 }
2309 else
2310 {
2311 //Delete selection
2312 for(auto x = 0; x < 16; ++x)
2313 for(auto y = 0; y < 16; ++y)
2314 {
2315 if(floating_sel)
2316 {
2317 floatsel[x+(y<<4)] = 0;
2318 }
2319 else if(is_in_selection(x,y))
2320 {
2321 unpackbuf[(y<<4)+x] = 0;
2322 }
2323 }
2324 }
2325 pack_tile(newtilebuf, unpackbuf, tile);
2326 redraw=true;
2327 }
2328 break;
2329
2330 case KEY_A:
2331 clear_selection_grid();
2332 invert_selection_grid();
2333 redraw=true;
2334 break;
2335
2336 case KEY_D:
2337 clear_selection_grid();
2338 redraw=true;
2339 break;
2340
2341 case KEY_I:
2342 invert_selection_grid();
2343 redraw=true;
2344 break;
2345
2346 case KEY_H:
2347 flip^=1;
2348 normalize(tile,tile,0,flip);
2349 flip=0;
2350 redraw=true;
2351 break;
2352
2353 case KEY_V:
2354 flip^=2;
2355 normalize(tile,tile,0,flip);
2356 flip=0;
2357 redraw=true;
2358 break;
2359
2360 case KEY_F12:
2361 onSnapshot();
2362 break;
2363
2364 case KEY_R:
2365 {
2366 //if(CHECK_CTRL_CMD))
2367 // {
2368 //do_recolor(tile); redraw=true; saved=false;
2369 // }
2370 //else
2371 // {
2372 go_tiles();
2373 rotate_tile(tile,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
2374 redraw=true;
2375 saved=false;
2376 break;
2377 }
2378
2379 case KEY_EQUALS:
2380 case KEY_PLUS_PAD:
2381 {
2382 if(CHECK_CTRL_CMD ||
2383 key[KEY_ALT] || key[KEY_ALTGR])
2384 {
2385 for(int32_t i=0; i<undocount; i++)
2386 undotile[i]=newtilebuf[tile].data[i];
2387 for(auto x = 0; x < 16; ++x)
2388 for(auto y = 0; y < 16; ++y)
2389 undoselgrid[x][y] = selection_grid[x+1][y+1];
2390 for(auto q = 0; q < 256; ++q)
2391 undofloatsel[q] = floatsel[q];
2392 undo_is_floatsel = floating_sel;
2393
2394 if(key[KEY_ALT] || key[KEY_ALTGR])
2395 shift_tile_colors(tile, 16, false);
2396 else
2397 shift_tile_colors(tile, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2398 }
2399 else
2400 cs = (cs<13) ? cs+1:0;
2401
2402 redraw=true;
2403 break;
2404 }
2405
2406 case KEY_MINUS:
2407 case KEY_MINUS_PAD:
2408 {
2409 if(CHECK_CTRL_CMD ||
2410 key[KEY_ALT] || key[KEY_ALTGR])
2411 {
2412 for(int32_t i=0; i<undocount; i++)
2413 undotile[i]=newtilebuf[tile].data[i];
2414 for(auto x = 0; x < 16; ++x)
2415 for(auto y = 0; y < 16; ++y)
2416 undoselgrid[x][y] = selection_grid[x+1][y+1];
2417 for(auto q = 0; q < 256; ++q)
2418 undofloatsel[q] = floatsel[q];
2419 undo_is_floatsel = floating_sel;
2420
2421 if(key[KEY_ALT] || key[KEY_ALTGR])
2422 shift_tile_colors(tile, -16, false);
2423 else
2424 shift_tile_colors(tile, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2425 }
2426 else
2427 cs = (cs>0) ? cs-1:13;
2428
2429 redraw=true;
2430 break;
2431 }
2432
2433 case KEY_SPACE:
2434 gridmode=(gridmode+1)%gm_max;
2435 redraw=true;
2436 break;
2437
2438 case KEY_Z:
2439 if(!ctrl)
2440 break;
2441 //Ctrl+Z == undo
2442 [[fallthrough]];
2443 case KEY_U:
2444 for(int32_t i=0; i<undocount; i++)
2445 zc_swap(undotile[i],newtilebuf[tile].data[i]);
2446
2447 for(auto x = 0; x < 16; ++x)
2448 for(auto y = 0; y < 16; ++y)
2449 zc_swap(selection_grid[x+1][y+1], undoselgrid[x][y]);
2450
2451 for(auto q = 0; q < 256; ++q)
2452 zc_swap(undofloatsel[q], floatsel[q]);
2453 zc_swap(undo_is_floatsel, floating_sel);
2454
2455 redraw=true;
2456 break;
2457
2458 case KEY_S:
2459 if(CHECK_CTRL_CMD)
2460 {
2461 for(int32_t i=0; i<undocount; i++)
2462 {
2463 undotile[i]=newtilebuf[tile].data[i];
2464 }
2465 for(auto x = 0; x < 16; ++x)
2466 for(auto y = 0; y < 16; ++y)
2467 undoselgrid[x][y] = selection_grid[x+1][y+1];
2468 for(auto q = 0; q < 256; ++q)
2469 undofloatsel[q] = floatsel[q];
2470 undo_is_floatsel = floating_sel;
2471
2472 unpack_tile(newtilebuf, tile, 0, false);
2473
2474 if(has_selection())
2475 {
2476 for(int32_t i=0; i<256; i++)
2477 {
2478 if(!is_in_selection(i%16,i/16))
2479 continue;
2480 if(unpackbuf[i]==c1)
2481 {
2482 unpackbuf[i]=c2;
2483 }
2484 else if(unpackbuf[i]==c2)
2485 {
2486 unpackbuf[i]=c1;
2487 }
2488 if(floating_sel)
2489 {
2490 if(floatsel[i]==c1)
2491 {
2492 floatsel[i]=c2;
2493 }
2494 else if(floatsel[i]==c2)
2495 {
2496 floatsel[i]=c1;
2497 }
2498 }
2499 }
2500 }
2501 else
2502 {
2503 for(int32_t i=0; i<256; i++)
2504 {
2505 if(unpackbuf[i]==c1)
2506 {
2507 unpackbuf[i]=c2;
2508 }
2509 else if(unpackbuf[i]==c2)
2510 {
2511 unpackbuf[i]=c1;
2512 }
2513 }
2514 }
2515
2516 pack_tile(newtilebuf, unpackbuf,tile);
2517 }
2518
2519 zc_swap(c1,c2);
2520 redraw=true;
2521 break;
2522
2523 case KEY_UP:
2524 if(CHECK_CTRL_CMD)
2525 {
2526 unfloat_selection();
2527 tile=zc_max(0,tile-TILES_PER_ROW);
2528 undocount = tilesize(newtilebuf[tile].format);
2529
2530 for(int32_t i=0; i<undocount; i++)
2531 {
2532 undotile[i]=newtilebuf[tile].data[i];
2533 oldtile[i]=undotile[i];
2534 }
2535
2536 redraw=true;
2537 }
2538 else
2539 {
2540 for(int32_t i=0; i<undocount; i++)
2541 {
2542 undotile[i]=newtilebuf[tile].data[i];
2543 }
2544 for(auto x = 0; x < 16; ++x)
2545 for(auto y = 0; y < 16; ++y)
2546 undoselgrid[x][y] = selection_grid[x+1][y+1];
2547 for(auto q = 0; q < 256; ++q)
2548 undofloatsel[q] = floatsel[q];
2549 undo_is_floatsel = floating_sel;
2550 if(has_selection())
2551 {
2552 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2553 wrap_sel_tile(-1, 0);
2554 shift_selection_grid(0, -1);
2555 }
2556 else wrap_tile(tile, -1, 0, false);
2557 redraw=true;
2558 }
2559 break;
2560
2561 case KEY_DOWN:
2562 if(CHECK_CTRL_CMD)
2563 {
2564 unfloat_selection();
2565 tile=zc_min(tile+TILES_PER_ROW,NEWMAXTILES-1);
2566 undocount = tilesize(newtilebuf[tile].format);
2567
2568 for(int32_t i=0; i<undocount; i++)
2569 {
2570 undotile[i]=newtilebuf[tile].data[i];
2571 oldtile[i]=undotile[i];
2572 }
2573
2574 redraw=true;
2575 }
2576 else
2577 {
2578 for(int32_t i=0; i<undocount; i++)
2579 {
2580 undotile[i]=newtilebuf[tile].data[i];
2581 }
2582 for(auto x = 0; x < 16; ++x)
2583 for(auto y = 0; y < 16; ++y)
2584 undoselgrid[x][y] = selection_grid[x+1][y+1];
2585 for(auto q = 0; q < 256; ++q)
2586 undofloatsel[q] = floatsel[q];
2587 undo_is_floatsel = floating_sel;
2588 if(has_selection())
2589 {
2590 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2591 wrap_sel_tile(1, 0);
2592 shift_selection_grid(0, 1);
2593 }
2594 else wrap_tile(tile, 1, 0, false);
2595 redraw=true;
2596 }
2597 break;
2598
2599 case KEY_LEFT:
2600 if(CHECK_CTRL_CMD)
2601 {
2602 unfloat_selection();
2603 tile=zc_max(0,tile-1);
2604 undocount = tilesize(newtilebuf[tile].format);
2605
2606 for(int32_t i=0; i<undocount; i++)
2607 {
2608 undotile[i]=newtilebuf[tile].data[i];
2609 oldtile[i]=undotile[i];
2610 }
2611
2612 redraw=true;
2613 }
2614 else
2615 {
2616 for(int32_t i=0; i<undocount; i++)
2617 {
2618 undotile[i]=newtilebuf[tile].data[i];
2619 }
2620 for(auto x = 0; x < 16; ++x)
2621 for(auto y = 0; y < 16; ++y)
2622 undoselgrid[x][y] = selection_grid[x+1][y+1];
2623 for(auto q = 0; q < 256; ++q)
2624 undofloatsel[q] = floatsel[q];
2625 undo_is_floatsel = floating_sel;
2626 if(has_selection())
2627 {
2628 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2629 wrap_sel_tile(0, -1);
2630 shift_selection_grid(-1, 0);
2631 }
2632 else wrap_tile(tile, 0, -1, false);
2633 redraw=true;
2634 }
2635 break;
2636
2637 case KEY_RIGHT:
2638 if(CHECK_CTRL_CMD)
2639 {
2640 unfloat_selection();
2641 tile=zc_min(tile+1, NEWMAXTILES-1);
2642 undocount = tilesize(newtilebuf[tile].format);
2643
2644 for(int32_t i=0; i<undocount; i++)
2645 {
2646 undotile[i]=newtilebuf[tile].data[i];
2647 oldtile[i]=undotile[i];
2648 }
2649
2650 redraw=true;
2651 }
2652 else
2653 {
2654 for(int32_t i=0; i<undocount; i++)
2655 {
2656 undotile[i]=newtilebuf[tile].data[i];
2657 }
2658 for(auto x = 0; x < 16; ++x)
2659 for(auto y = 0; y < 16; ++y)
2660 undoselgrid[x][y] = selection_grid[x+1][y+1];
2661 for(auto q = 0; q < 256; ++q)
2662 undofloatsel[q] = floatsel[q];
2663 undo_is_floatsel = floating_sel;
2664 if(has_selection())
2665 {
2666 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2667 wrap_sel_tile(0, 1);
2668 shift_selection_grid(1, 0);
2669 }
2670 else wrap_tile(tile, 0, 1, false);
2671 redraw=true;
2672 }
2673 break;
2674 case KEY_0: case KEY_1: case KEY_2: case KEY_3:
2675 case KEY_4: case KEY_5: case KEY_6: case KEY_7:
2676 case KEY_8: case KEY_9:
2677 case KEY_0_PAD: case KEY_1_PAD: case KEY_2_PAD: case KEY_3_PAD:
2678 case KEY_4_PAD: case KEY_5_PAD: case KEY_6_PAD: case KEY_7_PAD:
2679 case KEY_8_PAD: case KEY_9_PAD:
2680 {
2681 int t = k - ((k>KEY_9) ? KEY_1_PAD : KEY_1);
2682 if(unsigned(t) < t_max)
2683 {
2684 if(old_tool != -1)
2685 old_tool = t;
2686 else tool = t;
2687 }
2688 break;
2689 }
2690 case KEY_TAB:
2691 {
2692 if(key_shifts & KB_CTRL_FLAG)
2693 {
2694 xmode = (xmode+1)%XMODE_MAX;
2695 if(!xmode)
2696 bgmode = (bgmode+1)%BGMODE_MAX;
2697 }
2698 else if(key_shifts & KB_SHIFT_FLAG)
2699 hide_grid = !hide_grid;
2700 else show_quartgrid = !show_quartgrid;
2701 redraw = true;
2702 break;
2703 }
2704 }
2705 clear_keybuf();
2706 }
2707
2708 if(!gui_mouse_b())
2709 {
2710 if(is_selecting())
2711 {
2712 unfloat_selection();
2713 int32_t x1=zc_min(selecting_x1,selecting_x2);
2714 int32_t x2=zc_max(selecting_x1,selecting_x2);
2715 int32_t y1=zc_min(selecting_y1,selecting_y2);
2716 int32_t y2=zc_max(selecting_y1,selecting_y2);
2717
2718 if(select_mode==0)
2719 {
2720 clear_selection_grid();
2721 }
2722
2723 for(int32_t x=x1; x<=x2; ++x)
2724 {
2725 for(int32_t y=y1; y<=y2; ++y)
2726 {
2727 selection_grid[x+1][y+1]=((select_mode<2)?(1):(((select_mode==2)?(0):(selection_grid[x+1][y+1]))));
2728 }
2729 }
2730
2731 if(select_mode==3)
2732 {
2733 for(int32_t y=0; y<16; ++y)
2734 {
2735 for(int32_t x=0; x<x1; ++x)
2736 {
2737 selection_grid[x+1][y+1]=0;
2738 }
2739
2740 for(int32_t x=x2+1; x<16; ++x)
2741 {
2742 selection_grid[x+1][y+1]=0;
2743 }
2744 }
2745
2746 for(int32_t x=x1; x<=x2; ++x)
2747 {
2748 for(int32_t y=0; y<y1; ++y)
2749 {
2750 selection_grid[x+1][y+1]=0;
2751 }
2752
2753 for(int32_t y=y2+1; y<16; ++y)
2754 {
2755 selection_grid[x+1][y+1]=0;
2756 }
2757 }
2758 }
2759 }
2760
2761 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2762 did_wand_select=false;
2763 }
2764
2765 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
2766 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2767 bool ctrl=CHECK_CTRL_CMD;
2768 static int32_t last_tool_val = 0;
2769
2770 if(tool==t_select||tool==t_wand)
2771 {
2772 if(!drawing)
2773 {
2774 int32_t type=0;
2775
2776 if(has_selection())
2777 {
2778 if(shift)
2779 {
2780 type+=1;
2781 }
2782
2783 if(alt)
2784 {
2785 type+=2;
2786 }
2787 }
2788
2789 if(type!=select_mode)
2790 {
2791 select_mode=type;
2792
2793 if(isinRect(temp_mouse_x,temp_mouse_y-(tool==t_fill ? (14) : 0),zoomtile.x,zoomtile.y,zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2794 set_tool_sprite(tool,type);
2795 }
2796 }
2797 }
2798 else if(alt||ctrl)
2799 {
2800 if(old_tool==-1)
2801 {
2802 old_tool = tool;
2803 tool_cur = -1;
2804 }
2805 if(alt&&ctrl)
2806 tool = t_recolor;
2807 else if(alt)
2808 tool = t_eyedropper;
2809 else tool = t_fill;
2810 }
2811 else if(old_tool!=-1)
2812 {
2813 tool = old_tool;
2814 old_tool = -1;
2815 tool_cur = -1;
2816 redraw = true;
2817 }
2818 if(last_tool_val != tool)
2819 {
2820 redraw = true;
2821 tool_cur = -1;
2822 update_tool_cursor();
2823 last_tool_val = tool;
2824 }
2825
2826 if(!bdown)
2827 {
2828 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2829 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2830 }
2831
2832 if(gui_mouse_b()==1 && !bdown) //pressed the left mouse button
2833 {
2834 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2835 {
2836 if(tool==t_move || tool==t_fill)
2837 {
2838 set_tool_sprite(tool,1);
2839
2840 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2841 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2842 }
2843
2844 for(int32_t i=0; i<undocount; i++)
2845 {
2846 undotile[i]=newtilebuf[tile].data[i];
2847 }
2848 for(auto x = 0; x < 16; ++x)
2849 for(auto y = 0; y < 16; ++y)
2850 undoselgrid[x][y] = selection_grid[x+1][y+1];
2851 for(auto q = 0; q < 256; ++q)
2852 undofloatsel[q] = floatsel[q];
2853 undo_is_floatsel = floating_sel;
2854
2855 drawing=1;
2856 }
2857
2858 if(ok_button.rect(temp_mouse_x,temp_mouse_y))
2859 {
2860 if(do_text_button(ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK"))
2861 {
2862 done=2;
2863 }
2864 }
2865
2866 if(cancel_button.rect(temp_mouse_x,temp_mouse_y))
2867 {
2868 if(do_text_button(cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel"))
2869 {
2870 done=1;
2871 }
2872 }
2873
2874 if(edit_button.rect(temp_mouse_x,temp_mouse_y))
2875 {
2876 if(do_text_button(edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal"))
2877 {
2878 colors_menu.pop(edit_button.x+2,edit_button.y-40);
2879 get_palette(tpal);
2880
2881 if(newtilebuf[tile].format==tf4Bit)
2882 {
2883 invcol=makecol8((63-tpal[CSET(cs)].r)*255/63,(63-tpal[CSET(cs)].g)*255/63,(63-tpal[CSET(cs)].b)*255/63);
2884 }
2885 else
2886 {
2887 invcol=makecol8((63-tpal[0].r)*255/63,(63-tpal[0].g)*255/63,(63-tpal[0].b)*255/63);
2888 }
2889
2890 redraw=true;
2891 }
2892 }
2893
2894 int sqr_clicked;
2895 if(show_quartgrid && qgrid_tool(tool))
2896 {
2897 sqr_clicked = reflbtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2898 if(sqr_clicked > -1)
2899 {
2900 auto& sqr = reflbtn_grid.subsquare(sqr_clicked);
2901 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[sqr_clicked]))
2902 refl_flags ^= (1<<sqr_clicked);
2903 }
2904 }
2905 sqr_clicked = xmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2906 if(sqr_clicked > -1)
2907 {
2908 auto& sqr = xmodebtn_grid.subsquare(sqr_clicked);
2909 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[sqr_clicked]))
2910 xmode = sqr_clicked;
2911 }
2912 sqr_clicked = bgmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2913 if(sqr_clicked > -1)
2914 {
2915 auto& sqr = bgmodebtn_grid.subsquare(sqr_clicked);
2916 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[sqr_clicked]))
2917 bgmode = sqr_clicked;
2918 }
2919
2920 if(showcolortip)
2921 {
2922 if(color_info.rect(temp_mouse_x,temp_mouse_y))
2923 {
2924 showcolortip = 0;
2925 zc_set_config("ZQ_GUI","tile_edit_colornames",0);
2926 }
2927 }
2928 else
2929 {
2930 if(color_info_btn.rect(temp_mouse_x,temp_mouse_y))
2931 {
2932 if(do_text_button(color_info_btn.x,color_info_btn.y,color_info_btn.w,color_info_btn.h,"Show Colors"))
2933 {
2934 showcolortip = 1;
2935 zc_set_config("ZQ_GUI","tile_edit_colornames",1);
2936 redraw=true;
2937 }
2938 }
2939 }
2940
2941 if(hlcbox.rect(temp_mouse_x,temp_mouse_y))
2942 {
2943 if(do_checkbox(screen2,hlcbox.x,hlcbox.y,hlcbox.w,hlcbox.h,tthighlight))
2944 {
2945 zc_set_config("ZQ_GUI","tile_edit_fancyhighlight",tthighlight);
2946 redraw=true;
2947 }
2948 }
2949 if(quartgrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2950 {
2951 if(do_checkbox(screen2,quartgrid_cbox.x,quartgrid_cbox.y,quartgrid_cbox.w,quartgrid_cbox.h,show_quartgrid))
2952 redraw=true;
2953 }
2954 if(hidegrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2955 {
2956 if(do_checkbox(screen2,hidegrid_cbox.x,hidegrid_cbox.y,hidegrid_cbox.w,hidegrid_cbox.h,hide_grid))
2957 redraw=true;
2958 }
2959
2960 switch(newtilebuf[tile].format)
2961 {
2962 case tf4Bit:
2963 {
2964 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
2965 if(ind > -1)
2966 {
2967 c1 = ind;
2968 redraw=true;
2969 }
2970 break;
2971 }
2972 case tf8Bit:
2973 {
2974 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
2975 if(ind > -1)
2976 {
2977 c1 = ind;
2978 redraw=true;
2979 }
2980 break;
2981 }
2982 }
2983
2984
2985 int32_t newtool = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
2986 if(newtool > -1 && newtool < t_max)
2987 {
2988 tool=newtool;
2989 redraw=true;
2990 }
2991
2992 if(x_btn.rect(temp_mouse_x,temp_mouse_y))
2993 {
2994 if(do_x_button(screen, x_btn.x, x_btn.y))
2995 {
2996 done=1;
2997 }
2998 }
2999 if(info_btn.rect(temp_mouse_x,temp_mouse_y))
3000 {
3001 if(do_question_button(screen, info_btn.x, info_btn.y))
3002 {
3003 show_edit_tile_help();
3004 }
3005 }
3006
3007 bdown=true;
3008 }
3009
3010 if(gui_mouse_b()&2 && !bdown) //pressed the right mouse button
3011 {
3012 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3013 {
3014 if(tool==t_move || tool==t_fill)
3015 {
3016 set_tool_sprite(tool,1);
3017
3018 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
3019 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
3020 }
3021
3022 for(int32_t i=0; i<undocount; i++)
3023 {
3024 undotile[i]=newtilebuf[tile].data[i];
3025 }
3026 for(auto x = 0; x < 16; ++x)
3027 for(auto y = 0; y < 16; ++y)
3028 undoselgrid[x][y] = selection_grid[x+1][y+1];
3029 for(auto q = 0; q < 256; ++q)
3030 undofloatsel[q] = floatsel[q];
3031 undo_is_floatsel = floating_sel;
3032
3033 drawing=2;
3034 }
3035
3036 switch(newtilebuf[tile].format)
3037 {
3038 case tf4Bit:
3039 {
3040 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
3041 if(ind > -1)
3042 {
3043 c2 = ind;
3044 redraw=true;
3045 }
3046 break;
3047 }
3048 case tf8Bit:
3049 {
3050 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
3051 if(ind > -1)
3052 {
3053 c2 = ind;
3054 redraw=true;
3055 }
3056 break;
3057 }
3058 }
3059
3060 bdown=true;
3061 }
3062
3063 if(bdown&&!gui_mouse_b()) //released the buttons
3064 {
3065 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3066 {
3067 if(tool==t_move || tool==t_fill)
3068 {
3069 set_tool_sprite(tool,0);
3070 }
3071 }
3072 }
3073
3074 if(drawing && zoomtile.rect(temp_mouse_x,temp_mouse_y)) //inside the zoomed tile window
3075 {
3076 int32_t ind = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3077 int32_t x=ind%zoomtile.w;
3078 int32_t y=ind/zoomtile.w;
3079
3080 bool reset_draw = false;
3081
3082 if(__pixel_draw(x,y,tile,flip))
3083 reset_draw = true;
3084 if(show_quartgrid)
3085 {
3086 auto tmp_sel_mode = select_mode;
3087 if(tool == t_wand && select_mode == 0)
3088 select_mode = 1;
3089 if(qgrid_tool(tool))
3090 {
3091 if(refl_flags & (1<<REFL_HFLIP))
3092 if(__pixel_draw(15-x,y,tile,flip))
3093 reset_draw = true;
3094 if(refl_flags & (1<<REFL_VFLIP))
3095 if(__pixel_draw(x,15-y,tile,flip))
3096 reset_draw = true;
3097 //Diagonal flip and 180° rotation are the same!
3098 if(refl_flags & ((1<<REFL_DBLFLIP)|(1<<REFL_180)))
3099 if(__pixel_draw(15-x,15-y,tile,flip))
3100 reset_draw = true;
3101 if(refl_flags & (1<<REFL_90CW))
3102 if(__pixel_draw(15-y,x,tile,flip))
3103 reset_draw = true;
3104 if(refl_flags & (1<<REFL_90CCW))
3105 if(__pixel_draw(y,15-x,tile,flip))
3106 reset_draw = true;
3107 }
3108 select_mode = tmp_sel_mode;
3109 }
3110
3111 if(reset_draw)
3112 drawing = 0;
3113 redraw=true;
3114 }
3115
3116 if(gui_mouse_b()==0)
3117 {
3118 bdown=false;
3119 drawing=0;
3120 }
3121
3122 temp_x=(gui_mouse_x()-zoomtile.x)/zoomtile.xscale;
3123 temp_y=(gui_mouse_y()-zoomtile.y)/zoomtile.yscale;
3124
3125 {
3126 tile_x=temp_x;
3127 tile_y=temp_y;
3128 redraw=true;
3129 }
3130
3131 const char *toolnames[t_max]=
3132 {
3133 "Pen\nDraw Single Pixels", "Fill\nCtrl", "Replace Color\nCtrl+Alt", "Grab Color\nAlt", "Move\nMove Selections", "Select Pixels", "Select Color"
3134 };
3135
3136 int32_t toolbtn = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
3137 if(toolbtn > -1 && toolbtn < t_max)
3138 {
3139 int32_t column = toolbtn%tool_btns.w;
3140 int32_t row = toolbtn/tool_btns.w;
3141
3142 update_tooltip(temp_mouse_x,temp_mouse_y,tool_btns.x+(column*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale, toolnames[toolbtn]);
3143 redraw=true;
3144 }
3145 /* Highlight the hovered pixel? Eh, maybe too much?
3146 int32_t hov_pix = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3147 if(hov_pix > -1)
3148 {
3149 int32_t column = hov_pix%zoomtile.w;
3150 int32_t row = hov_pix/zoomtile.w;
3151
3152 update_tooltip(temp_mouse_x,temp_mouse_y,zoomtile.x+(column*zoomtile.xscale),zoomtile.y+(row*zoomtile.yscale),zoomtile.xscale,zoomtile.yscale, NULL);
3153 redraw=true;
3154 }*/
3155
3156 if(redraw)
3157 {
3158 custom_vsync();
3159 draw_edit_scr(tile,flip,cs,oldtile, false);
3160 }
3161 else
3162 {
3163 bool hs=has_selection();
3164
3165 if(hs)
3166 {
3167 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
3168 }
3169
3170 custom_vsync();
3171
3172 if(hs)
3173 {
3174 // blit(screen2, screen, 79, 31, 79, 31, 129, 129);
3175 blit(screen2, screen, zoomtile.x-1,zoomtile.y-1, zoomtile.x-1,zoomtile.y-1, (zoomtile.w*zoomtile.xscale)+1, (zoomtile.h*zoomtile.yscale)+1);
3176 }
3177
3178 update_tool_cursor();
3179 SCRFIX();
3180 }
3181
3182 }
3183 while(!done);
3184
3185 unfloat_selection();
3186 clear_selection_grid();
3187
3188 while(gui_mouse_b())
3189 {
3190 /* do nothing */
3191 rest(1);
3192 }
3193
3194 if(done==1)
3195 {
3196 for(int32_t i=0; i<undocount; i++)
3197 {
3198 newtilebuf[tile].data[i]=oldtile[i];
3199 }
3200 }
3201 else
3202 {
3203 byte *buf = new byte[undocount];
3204
3205 // put back old tile
3206 for(int32_t i=0; i<undocount; i++)
3207 {
3208 buf[i] = newtilebuf[tile].data[i];
3209 newtilebuf[tile].data[i] = oldtile[i];
3210 }
3211
3212 // go
3213 go_tiles();
3214
3215 // replace old tile with new one again
3216 for(int32_t i=0; i<undocount; i++)
3217 {
3218 newtilebuf[tile].data[i] = buf[i];
3219 }
3220
3221 // usetiles=true;
3222 saved=false;
3223
3224 if(buf!=NULL)
3225 {
3226 delete[] buf;
3227 }
3228 }
3229
3230 MouseSprite::set(ZQM_NORMAL);
3231 register_blank_tiles();
3232 register_used_tiles();
3233 clear_tooltip();
3234 comeback();
3235 destroy_bitmap(selection_pattern);
3236 destroy_bitmap(selecting_pattern);
3237 destroy_bitmap(intersection_pattern);
3238 font = oldfont;
3239 popup_zqdialog_end();
3240 }
3241
3242 /* Grab Tile Code */
3243
3244 enum recolorState { rcNone, rc4Bit, rc8Bit };
3245
3246 BITMAP* original_imagebuf_bitmap=NULL;
3247 void *imagebuf=NULL;
3248 int32_t imagebuf_bitmap_scale=0;
3249 #define IMAGEBUF_SCALE (imagebuf_bitmap_scale > 0 ? imagebuf_bitmap_scale : 1.0 / -imagebuf_bitmap_scale)
3250 int32_t imagesize=0;
3251 int32_t tilecount=0;
3252 int32_t imagetype=0;
3253 int32_t imagex,imagey,selx,sely;
3254 int32_t bp=4,grabmode=16,romofs=0,romtilemode=0, romtilecols=8;
3255 bool nesmode=false;
3256 int32_t grabmask=0;
3257 recolorState recolor=rcNone;
3258 PALETTE imagepal;
3259
3260 /* bestfit_color:
3261 * Searches a palette for the color closest to the requested R, G, B value.
3262 */
3263 int32_t bestfit_cset_color(int32_t cs, int32_t r, int32_t g, int32_t b)
3264 {
3265 int32_t bestMatch = 0; // Color with the lowest total difference so far
3266 float bestTotalDiff = 100000; // Total difference between requested color and bestMatch
3267 float bestHighDiff = 100000; // Greatest difference of R, G, B between requested color and bestMatch
3268
3269 for(int32_t i = 0; i < CSET_SIZE; i++)
3270 {
3271 byte *rgbByte;
3272
3273 // This seems to be right...
3274 if(cs==2 || cs==3 || cs==4)
3275 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + i) * 3;
3276 else if(cs==9)
3277 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + i) * 3;
3278 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3279 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + i) * 3;
3280 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3281 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + i) * 3;
3282 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3283 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + i) * 3;
3284 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3285 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + i) * 3;
3286 else
3287 rgbByte = colordata + (CSET(cs)+i)*3;
3288
3289 int32_t dr=r-*rgbByte;
3290 int32_t dg=g-*(rgbByte+1);
3291 int32_t db=b-*(rgbByte+2);
3292
3293 // Track both the total color difference and the single greatest
3294 // difference of R, G, B. The idea is that it's better to have
3295 // two or three small differences than one big one.
3296 // The differences are multiplied by different numbers to account
3297 // for the differences in perceived brightness of the three colors.
3298 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3299 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3300
3301 // Perfect match? Just stop here.
3302 if(totalDiff==0)
3303 return i;
3304
3305 if(totalDiff < bestTotalDiff || // Best match so far?
3306 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3307 {
3308 bestMatch=i;
3309 bestTotalDiff=totalDiff;
3310 bestHighDiff=highDiff;
3311 }
3312 }
3313
3314 return bestMatch;
3315 }
3316
3317 // Same as the above, but draws from all colors in CSets 0-11.
3318 int32_t bestfit_cset_color_8bit(int32_t r, int32_t g, int32_t b)
3319 {
3320 int32_t bestMatch = 0;
3321 float bestTotalDiff = 100000;
3322 float bestHighDiff = 100000;
3323
3324 for(int32_t i = 0; i < 192; i++) // 192 colors in CSets 0-11
3325 {
3326 byte *rgbByte;
3327
3328 int32_t cs=i>>4;
3329 if(cs==2 || cs==3 || cs==4)
3330 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + (i%16)) * 3;
3331 else if(cs==9)
3332 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + (i%16)) * 3;
3333 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3334 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + (i%16)) * 3;
3335 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3336 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + (i%16)) * 3;
3337 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3338 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + (i%16)) * 3;
3339 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3340 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + (i%16)) * 3;
3341 else
3342 rgbByte = colordata + i * 3;
3343
3344 int32_t dr=r-*rgbByte;
3345 int32_t dg=g-*(rgbByte+1);
3346 int32_t db=b-*(rgbByte+2);
3347
3348 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3349 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3350
3351 if(totalDiff==0) // Perfect match?
3352 return i;
3353
3354 if(totalDiff < bestTotalDiff || // Best match so far?
3355 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3356 {
3357 bestMatch=i;
3358 bestTotalDiff=totalDiff;
3359 bestHighDiff=highDiff;
3360 }
3361 }
3362
3363 return bestMatch;
3364 }
3365
3366 byte cset_reduce_table[PAL_SIZE];
3367
3368 void calc_cset_reduce_table(PALETTE pal, int32_t cs)
3369 {
3370 for(int32_t i=0; i<PAL_SIZE; i++)
3371 {
3372 cset_reduce_table[i]=(bestfit_cset_color(cs, pal[i].r, pal[i].g, pal[i].b)&0x0F);
3373 }
3374 }
3375
3376 void calc_cset_reduce_table_8bit(PALETTE pal)
3377 {
3378 for(int32_t i=0; i<PAL_SIZE; i++)
3379 {
3380 cset_reduce_table[i]=bestfit_cset_color_8bit(pal[i].r, pal[i].g, pal[i].b);
3381 }
3382 }
3383
3384 void puttileROM(BITMAP *dest,int32_t x,int32_t y,byte *src,int32_t cs)
3385 {
3386 //storage space for the grabbed image
3387 byte buf[64];
3388 memset(buf,0,64);
3389 byte *oldsrc=src;
3390
3391 //for 8 lines in the source image...
3392 for(int32_t line=0; line<(nesmode?4:8); line++)
3393 {
3394 //bx is the pixel at the start of a line in the storage buffer
3395 int32_t bx=line<<(nesmode?4:3);
3396 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3397 byte b=src[(bp&1)?line:line<<1];
3398
3399 //fill the storage buffer with data from the source image
3400 for(int32_t i=7; i>=0; --i)
3401 {
3402 buf[bx+i] = (b&1)+(cs<<4);
3403 b>>=1;
3404 }
3405 }
3406
3407 ++src;
3408
3409 for(int32_t p=1; p<bp; p++)
3410 {
3411 for(int32_t line=0; line<(nesmode?4:8); line++)
3412 {
3413 int32_t bx=line<<(nesmode?4:3);
3414 byte b=src[(bp&1)?line:line<<1];
3415
3416 for(int32_t i=7; i>=0; --i)
3417 {
3418 if(nesmode)
3419 {
3420 buf[bx+8+i] = (b&1)+(cs<<4);
3421 }
3422 else
3423 {
3424 buf[bx+i] |= (b&1)<<p;
3425 }
3426
3427 b>>=1;
3428 }
3429 }
3430
3431 if(p&1)
3432 {
3433 src+=15;
3434 }
3435 else
3436 {
3437 ++src;
3438 }
3439 }
3440
3441
3442 if(nesmode)
3443 {
3444 src=oldsrc;
3445
3446 for(int32_t counter=0; counter<2; ++counter, ++src)
3447 {
3448 //for 8 lines in the source image...
3449 for(int32_t line=0; line<4; line++)
3450 {
3451 //bx is the pixel at the start of a line in the storage buffer
3452 int32_t bx=line<<4;
3453 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3454 byte b=src[(line+4)<<1];
3455
3456 //fill the storage buffer with data from the source image
3457 for(int32_t i=7; i>=0; --i)
3458 {
3459 // buf[bx+i] = (b&1)+(cs<<4);
3460 buf[bx+(counter<<3)+i] |= (b&1)<<1;
3461 b>>=1;
3462 }
3463 }
3464 }
3465 }
3466
3467 int32_t c=0;
3468
3469 switch(romtilemode)
3470 {
3471 case 0:
3472 case 1:
3473 case 2:
3474 for(int32_t j=0; j<8; j++)
3475 {
3476 for(int32_t i=0; i<8; i++)
3477 {
3478 putpixel(dest,x+i,y+j,buf[c++]);
3479 }
3480 }
3481
3482 break;
3483
3484 case 3:
3485 for(int32_t j=0; j<4; j++)
3486 {
3487 for(int32_t i=0; i<16; i++)
3488 {
3489 putpixel(dest,x+i,y+j,buf[c++]);
3490 }
3491 }
3492
3493 break;
3494 }
3495 }
3496
3497 const char *file_type[ftMAX]=
3498 {
3499 "None", "BIN", "BMP", "TIL", "ZGP", "QSU", "ZQT", "QST"
3500 };
3501
3502 void draw_grab_window()
3503 {
3504 int w = 640;
3505 int h = 480;
3506 int window_xofs=0;//(zq_screen_w-w-12)>>1;
3507 int window_yofs=0;//(zq_screen_h-h-25-6)>>1;
3508 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
3509 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+2+2-(79*2), FR_DEEP);
3510
3511 FONT *oldfont = font;
3512 font = get_zc_font(font_lfont);
3513 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Grab Tile(s)", true);
3514 font=oldfont;
3515 }
3516
3517 void draw_grab_scr(int32_t tile,int32_t cs,byte *newtile,int32_t black,int32_t white, int32_t width, int32_t height, byte *newformat)
3518 {
3519 width=width;
3520 height=height;
3521 white=white; // happy birthday compiler
3522
3523 int32_t yofs=0;
3524 //clear_to_color(screen2,bg);
3525 rectfill(screen2, 0, 0, 319, 159, black);
3526 rectfill(screen2,0,162,319,239,jwin_pal[jcBOX]);
3527 _allegro_hline(screen2, 0, 160, 319, jwin_pal[jcMEDLT]);
3528 _allegro_hline(screen2, 0, 161, 319, jwin_pal[jcLIGHT]);
3529 yofs=3;
3530
3531 // text_mode(-1);
3532 int32_t tileromcolumns=20;
3533
3534 switch(imagetype)
3535 {
3536 case ftBMP:
3537 if(recolor==rcNone)
3538 {
3539 blit((BITMAP*)imagebuf,screen2,imagex<<4,imagey<<4,0,0,320,160);
3540 }
3541 else
3542 {
3543 int32_t maxy=zc_min(160,((BITMAP*)imagebuf)->h);
3544 int32_t maxx=zc_min(320,((BITMAP*)imagebuf)->w);
3545
3546 for(int32_t y=0; y<maxy; y++)
3547 {
3548 if((imagey<<4)+y>=((BITMAP*)imagebuf)->h)
3549 {
3550 break;
3551 }
3552
3553 for(int32_t x=0; x<maxx; x++)
3554 {
3555 if((imagex<<4)+x>=((BITMAP*)imagebuf)->w)
3556 {
3557 break;
3558 }
3559
3560 if(recolor==rc8Bit)
3561 screen2->line[y][x]=cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]];
3562 else
3563 screen2->line[y][x]=(cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]])+(cs<<4);
3564 }
3565 }
3566 }
3567
3568 break;
3569
3570 case ftZGP:
3571 case ftQST:
3572 case ftZQT:
3573 case ftQSU:
3574 case ftTIL:
3575 {
3576 tiledata *hold = newtilebuf;
3577 newtilebuf = grabtilebuf;
3578 //fixme
3579 imagey = vbound(imagey, 0, MAXTILEROWS); //fixed -Z This can no longer crash if you scroll past the end of the tile pages. 6th June, 2020
3580 int32_t t=imagey*TILES_PER_ROW;
3581
3582 for(int32_t i=0; i<200; i++) // 10 rows, down to y=160
3583 {
3584 if(t <= tilecount)
3585 {
3586 puttile16(screen2,t,(i%TILES_PER_ROW)<<4,(i/TILES_PER_ROW)<<4,cs,0);
3587 }
3588
3589 ++t;
3590 }
3591
3592 newtilebuf = hold;
3593 //fixme
3594 }
3595 break;
3596
3597 case ftBIN:
3598 {
3599 int32_t ofs = (tileromcolumns*imagex + imagey) * 128*bp + romofs;
3600 byte *buf = (byte*)imagebuf;
3601
3602 switch(romtilemode)
3603 {
3604 case 0:
3605 for(int32_t y=0; y<160; y+=8)
3606 {
3607 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3608 {
3609 puttileROM(screen2,x,y,buf+ofs,cs);
3610 ofs+=8*bp;
3611 }
3612 }
3613
3614 for(int32_t y=0; y<160; y+=8)
3615 {
3616 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3617 {
3618 puttileROM(screen2,x+128,y,buf+ofs,cs);
3619 ofs+=8*bp;
3620 }
3621 }
3622
3623 break;
3624
3625 case 1:
3626 for(int32_t y=0; y<160; y+=16)
3627 {
3628 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3629 {
3630 puttileROM(screen2,x,y,buf+ofs,cs);
3631 ofs+=8*bp;
3632 puttileROM(screen2,x,y+8,buf+ofs,cs);
3633 ofs+=8*bp;
3634 }
3635 }
3636
3637 for(int32_t y=0; y<160; y+=16)
3638 {
3639 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3640 {
3641 puttileROM(screen2,x+128,y,buf+ofs,cs);
3642 ofs+=8*bp;
3643 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3644 ofs+=8*bp;
3645 }
3646 }
3647
3648 break;
3649
3650 case 2:
3651 for(int32_t y=0; y<160; y+=16)
3652 {
3653 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3654 {
3655 puttileROM(screen2,x,y,buf+ofs,cs);
3656 ofs+=8*bp;
3657 puttileROM(screen2,x+8,y,buf+ofs,cs);
3658 ofs+=8*bp;
3659 puttileROM(screen2,x,y+8,buf+ofs,cs);
3660 ofs+=8*bp;
3661 puttileROM(screen2,x+8,y+8,buf+ofs,cs);
3662 ofs+=8*bp;
3663 }
3664 }
3665
3666 for(int32_t y=0; y<160; y+=16)
3667 {
3668 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3669 {
3670 puttileROM(screen2,x+128,y,buf+ofs,cs);
3671 ofs+=8*bp;
3672 puttileROM(screen2,x+136,y,buf+ofs,cs);
3673 ofs+=8*bp;
3674 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3675 ofs+=8*bp;
3676 puttileROM(screen2,x+136,y+8,buf+ofs,cs);
3677 ofs+=8*bp;
3678 }
3679 }
3680
3681 break;
3682
3683 case 3:
3684 for(int32_t y=0; y<160; y+=16)
3685 {
3686 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3687 {
3688 puttileROM(screen2,x,y,buf+ofs,cs);
3689 ofs+=8*bp;
3690 puttileROM(screen2,x,y+4,buf+ofs,cs);
3691 ofs+=8*bp;
3692 puttileROM(screen2,x,y+8,buf+ofs,cs);
3693 ofs+=8*bp;
3694 puttileROM(screen2,x,y+12,buf+ofs,cs);
3695 ofs+=8*bp;
3696 }
3697 }
3698
3699 for(int32_t y=0; y<160; y+=16)
3700 {
3701 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3702 {
3703 puttileROM(screen2,x+128,y,buf+ofs,cs);
3704 ofs+=8*bp;
3705 puttileROM(screen2,x+128,y+4,buf+ofs,cs);
3706 ofs+=8*bp;
3707 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3708 ofs+=8*bp;
3709 puttileROM(screen2,x+128,y+12,buf+ofs,cs);
3710 ofs+=8*bp;
3711 }
3712 }
3713
3714 break;
3715 }
3716 }
3717 break;
3718 }
3719
3720 tiledata hold;
3721 bool holdblank = blank_tile_table[0];
3722
3723 if(is_valid_format(newtilebuf[0].format))
3724 {
3725 hold.format = newtilebuf[0].format;
3726 hold.data = (byte *)malloc(tilesize(hold.format));
3727 memcpy(hold.data, newtilebuf[0].data, tilesize(hold.format));
3728 }
3729 else
3730 {
3731 hold.format=tfInvalid;
3732 hold.data=NULL;
3733 }
3734
3735 newtilebuf[0].format=newformat[0];
3736 blank_tile_table[0] = false;
3737
3738 if(newtilebuf[0].data!=NULL)
3739 {
3740 free(newtilebuf[0].data);
3741 }
3742
3743 if(is_valid_format(newtilebuf[0].format))
3744 {
3745 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3746
3747 for(int32_t i=0; i<tilesize(newtilebuf[0].format); i++)
3748 {
3749 newtilebuf[0].data[i]=newtile[i];
3750 }
3751 }
3752 else
3753 {
3754 newtilebuf[0].data=NULL;
3755 }
3756
3757 puttile16(screen2,0,208,168+yofs,cs,0);
3758 overtile16(screen2,0,232,168+yofs,cs,0);
3759 newtilebuf[0].format=hold.format;
3760 blank_tile_table[0] = holdblank;
3761
3762 if(newtilebuf[0].data!=NULL)
3763 {
3764 free(newtilebuf[0].data);
3765 }
3766
3767 if(is_valid_format(newtilebuf[0].format))
3768 {
3769 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3770
3771 for(int32_t i=0; i<256; i++)
3772 {
3773 newtilebuf[0].data[i]=hold.data[i];
3774 }
3775 }
3776 else
3777 {
3778 newtilebuf[0].data=NULL;
3779 }
3780
3781 if(hold.data!=NULL)
3782 {
3783 free(hold.data);
3784 }
3785
3786 puttile16(screen2,tile,208,192+yofs,cs,0);
3787 overtile16(screen2,tile,232,192+yofs,cs,0);
3788
3789 rectfill(screen2,184,168+yofs,191,175+yofs,grabmask&1?vc(12):vc(7));
3790 rectfill(screen2,192,168+yofs,199,175+yofs,grabmask&2?vc(12):vc(7));
3791 rectfill(screen2,184,176+yofs,191,183+yofs,grabmask&4?vc(12):vc(7));
3792 rectfill(screen2,192,176+yofs,199,183+yofs,grabmask&8?vc(12):vc(7));
3793
3794 // rect(screen2,183,167,200,184,dvc(7*2));
3795 // rect(screen2,207,167,224,184,dvc(7*2));
3796 // rect(screen2,231,167,248,184,dvc(7*2));
3797 // rect(screen2,207,191,224,208,dvc(7*2));
3798 // rect(screen2,231,191,248,208,dvc(7*2));
3799
3800 /*
3801 rect(screen2,183,167,200,184,vc(14));
3802 rect(screen2,207,167,224,184,vc(14));
3803 rect(screen2,231,167,248,184,vc(14));
3804 rect(screen2,207,191,224,208,vc(14));
3805 rect(screen2,231,191,248,208,vc(14));
3806 */
3807 jwin_draw_frame(screen2,182,166+yofs,20,20,FR_DEEP);
3808 jwin_draw_frame(screen2,206,166+yofs,20,20,FR_DEEP);
3809 jwin_draw_frame(screen2,230,166+yofs,20,20,FR_DEEP);
3810 jwin_draw_frame(screen2,206,190+yofs,20,20,FR_DEEP);
3811 jwin_draw_frame(screen2,230,190+yofs,20,20,FR_DEEP);
3812 int32_t screen_xofs=6;
3813 int32_t screen_yofs=25;
3814 int winh = 511;
3815 int32_t mul = 2;
3816
3817 yofs=16;
3818
3819 custom_vsync();
3820
3821 stretch_blit(screen2,screen,0,0,320,240,screen_xofs,screen_yofs,640,480);
3822
3823 // Suspend the current font while draw_text_button does its work
3824 FONT* oldfont = font;
3825
3826 font = get_zc_font(font_lfont_l);
3827
3828 int txt_x = 8*mul;
3829 int rbtn_x = 255*mul;
3830 int max_fpath_wid = rbtn_x-2-txt_x;
3831 int max_fpath_wid2 = max_fpath_wid-text_length(font,"... ");
3832 // Interface
3833 switch(imagetype)
3834 {
3835 case 0:
3836 textprintf_ex(screen,font,txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s",imgstr[imagetype]);
3837 break;
3838
3839 case ftBMP:
3840 {
3841 std::string text = fmt::format("{} {}x{}, {:.2g}x zoom with , and .", imgstr[imagetype], original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, IMAGEBUF_SCALE);
3842 int text_x = txt_x;
3843 int text_y = (216 + yofs) * mul;
3844 // TODO: can almost use this, but drawing is offset. prob cuz drawing to a different bitmap than the normal screen bitmap? idk
3845 // int text_w = text_length(font, text.c_str());
3846 // int text_h = text_height(font);
3847 // static int grab_scale_tooltip_id = ttip_register_id();
3848 // ttip_install(grab_scale_tooltip_id, "zoom with , and .", text_x, text_y, text_w, text_h, text_x, text_y - 40);
3849 textprintf_ex(screen, font, text_x, text_y, jwin_pal[jcTEXTFG], jwin_pal[jcBOX], "%s", text.c_str());
3850
3851 draw_text_button(screen,117*mul,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Recolor",vc(1),vc(14),0,true);
3852 break;
3853 }
3854
3855 case ftZGP:
3856 case ftQST:
3857 case ftZQT:
3858 case ftQSU:
3859 case ftTIL:
3860 case ftBIN:
3861 textprintf_ex(screen,get_zc_font(font_lfont_l),txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s %d KB",imgstr[imagetype],imagesize>>10);
3862 break;
3863 }
3864
3865 textprintf_ex(screen,font,txt_x,(168+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"sel: %d %d",selx,sely);
3866 textprintf_ex(screen,font,txt_x,(176+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"pos: %d %d",imagex,imagey);
3867
3868 if(bp==8)
3869 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"8-bit");
3870 else
3871 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"cset: %d",cs);
3872 textprintf_ex(screen,font,txt_x,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"step: %d",grabmode);
3873
3874 if(imagetype==ftBIN)
3875 {
3876 textprintf_ex(screen,font,104*mul,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"bp: %d%s",bp,nesmode?" (NES)":"");
3877 textprintf_ex(screen,font,104*mul,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"ofs: %Xh",romofs);
3878 textprintf_ex(screen,font,104*mul,(208+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"m: %d",romtilemode);
3879 }
3880
3881 int fpath_y = (224+yofs)*mul;
3882 if(text_length(font,imagepath) <= max_fpath_wid)
3883 textout_ex(screen,font,imagepath,txt_x,fpath_y,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3884 else
3885 {
3886 char buf[2052] = {0};
3887 strncpy(buf,imagepath,2048);
3888 int len = strlen(buf);
3889 char *ptr = buf;
3890 char *endptr = buf+len;
3891 char *it = endptr;
3892 int tmpy = fpath_y;
3893 int tmph = text_height(font)+1;
3894 while(true)
3895 {
3896 if(tmpy+tmph > (winh-2))
3897 break; //Out of space!
3898 char c = *it;
3899 bool end = !c;
3900 *it = 0;
3901 int newlen = text_length(font,ptr);
3902 if(newlen <= (end ? max_fpath_wid : max_fpath_wid2))
3903 {
3904 if(end) //No stored character, string ended
3905 {
3906 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3907 break;
3908 }
3909 char t[5];
3910 t[0] = c;
3911 for(int q = 1; q < 5; ++q)
3912 t[q] = it[q];
3913 strcpy(it,"...");
3914 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3915 for(int q = 0; q < 5; ++q)
3916 it[q] = t[q];
3917 tmpy += tmph;
3918 ptr = it;
3919 it = endptr;
3920 }
3921 else
3922 {
3923 *it = c;
3924 --it;
3925 }
3926 }
3927 }
3928 draw_text_button(screen,rbtn_x,(168+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"OK",vc(1),vc(14),0,true);
3929 draw_text_button(screen,rbtn_x,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Cancel",vc(1),vc(14),0,true);
3930 draw_text_button(screen,rbtn_x,(216+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"File",vc(1),vc(14),0,true);
3931 draw_text_button(screen,117*mul,(166+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Leech",vc(1),vc(14),0,true);
3932
3933 //int32_t rectw = 16*mul;
3934 //rect(screen,selx+screen_xofs,sely+screen_yofs,selx+screen_xofs+((width-1)*rectw)+rectw-1,sely+screen_yofs+((height-1)*rectw)+rectw-1,white);
3935 SCRFIX();
3936 font = oldfont;
3937 }
3938
3939 RGB_MAP rgb_table;
3940 COLOR_MAP imagepal_table;
3941
3942
3943 extern void return_RAMpal_color(AL_CONST PALETTE pal, int32_t x, int32_t y, RGB *rgb)
3944 {
3945 //these are here to bypass compiler warnings about unused arguments
3946 x=x;
3947
3948 rgb->r = pal[y].r;
3949 rgb->g = pal[y].g;
3950 rgb->b = pal[y].b;
3951 }
3952
3953
3954 void load_imagebuf()
3955 {
3956 PACKFILE *f;
3957 //cache QRS
3958 //byte cached_rules[QUESTRULES_NEW_SIZE] = { 0 };
3959 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
3960 // {
3961 // cached_rules[q] = quest_rules[q];
3962 // }
3963 bool compressed=false;
3964 bool encrypted=false;
3965 tiledata *hold=newtilebuf;
3966 zquestheader tempheader;
3967 memset(&tempheader, 0, sizeof(zquestheader));
3968
3969 if(imagebuf)
3970 {
3971 switch(imagetype)
3972 {
3973 case ftBMP:
3974 if (original_imagebuf_bitmap != imagebuf)
3975 destroy_bitmap((BITMAP*)imagebuf);
3976 destroy_bitmap(original_imagebuf_bitmap);
3977 break;
3978
3979 case ftZGP:
3980 case ftQST:
3981 case ftZQT:
3982 case ftQSU:
3983 case ftTIL:
3984 clear_tiles(grabtilebuf);
3985 break;
3986
3987 case ftBIN:
3988 free(imagebuf);
3989 break;
3990 }
3991
3992 imagebuf=NULL;
3993 original_imagebuf_bitmap=NULL;
3994 }
3995
3996 selx=sely=romofs=0;
3997 bp=4;
3998 imagetype=filetype(imagepath);
3999
4000 dword section_id;
4001 dword section_version;
4002 dword section_cversion;
4003
4004 switch(imagetype)
4005 {
4006 case ftBMP:
4007 packfile_password("");
4008 memset(imagepal, 0, sizeof(PALETTE));
4009 original_imagebuf_bitmap = load_bitmap(imagepath,imagepal);
4010 imagesize = file_size_ex_password(imagepath,"");
4011 tilecount=0;
4012 create_rgb_table(&rgb_table, imagepal, NULL);
4013 rgb_map = &rgb_table;
4014 create_color_table(&imagepal_table, RAMpal, return_RAMpal_color, NULL);
4015
4016 if(!original_imagebuf_bitmap)
4017 {
4018 imagetype=0;
4019 }
4020 else
4021 {
4022 imagebuf = original_imagebuf_bitmap;
4023 imagebuf_bitmap_scale = 1;
4024 }
4025
4026 break;
4027
4028 case ftBIN:
4029 packfile_password("");
4030 imagesize = file_size_ex_password(imagepath, "");
4031 tilecount=0;
4032
4033 if(imagesize)
4034 {
4035 imagebuf = malloc(imagesize);
4036
4037 if(!readfile(imagepath,imagebuf,imagesize))
4038 {
4039 free(imagebuf);
4040 imagesize=0;
4041 imagetype=0;
4042 }
4043 }
4044
4045 break;
4046
4047 case ftTIL:
4048 packfile_password("");
4049 imagesize = file_size_ex_password(imagepath,"");
4050 f = pack_fopen_password(imagepath,F_READ,"");
4051
4052 if(!f)
4053 {
4054 goto error;
4055 }
4056
4057 if(!p_mgetl(&section_id,f))
4058 {
4059 goto error;
4060 }
4061
4062 if(section_id==ID_TILES)
4063 {
4064 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)==0)
4065 {
4066 goto error;
4067 }
4068 }
4069
4070 error:
4071 pack_fclose(f);
4072 tilecount=count_tiles(grabtilebuf);
4073 break;
4074
4075 case ftZGP:
4076 packfile_password("");
4077 imagesize = file_size_ex_password(imagepath, "");
4078 f=pack_fopen_password(imagepath,F_READ,"");
4079
4080 if(!f)
4081 {
4082 goto error2;
4083 }
4084
4085 if(!p_mgetl(&section_id,f))
4086 {
4087 goto error2;
4088 }
4089
4090 if(section_id!=ID_GRAPHICSPACK)
4091 {
4092 goto error2;
4093 }
4094
4095 //section version info
4096 if(!p_igetw(&section_version,f))
4097 {
4098 goto error2;
4099 }
4100
4101 if(!p_igetw(&section_cversion,f))
4102 {
4103 goto error2;
4104 }
4105
4106 //tiles
4107 if(!p_mgetl(&section_id,f))
4108 {
4109 goto error2;
4110 }
4111
4112 if(section_id==ID_TILES)
4113 {
4114 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)!=0)
4115 {
4116 goto error2;
4117 }
4118 }
4119
4120 error2:
4121 pack_fclose(f);
4122 tilecount=count_tiles(grabtilebuf);
4123 break;
4124
4125 case ftQST:
4126 encrypted=true;
4127 case ftZQT:
4128 compressed=true;
4129 case ftQSU:
4130 packfile_password("");
4131 imagesize = file_size_ex_password(imagepath, encrypted ? datapwd : "");
4132 newtilebuf=grabtilebuf;
4133 byte skip_flags[4];
4134
4135 for(int32_t i=0; i<skip_max; ++i)
4136 {
4137 set_bit(skip_flags,i,1);
4138 }
4139
4140 set_bit(skip_flags,skip_tiles,0);
4141 set_bit(skip_flags,skip_header,0);
4142 int ret = loadquest(imagepath,&tempheader,&QMisc,customtunes,true,skip_flags);
4143 if (ret)
4144 {
4145 imagetype=0;
4146 imagesize=0;
4147 clear_tiles(grabtilebuf);
4148 chop_path(imagepath);
4149 }
4150
4151 if (!ret && encrypted && compressed)
4152 {
4153 if(quest_access(imagepath, &tempheader) != 1)
4154 {
4155 imagetype=0;
4156 imagesize=0;
4157 clear_tiles(grabtilebuf);
4158 chop_path(imagepath);
4159 }
4160 }
4161
4162 //setPackfilePassword(NULL);
4163 newtilebuf=hold;
4164 tilecount=count_tiles(grabtilebuf);
4165 break;
4166 }
4167
4168 rgb_map = &zq_rgb_table;
4169 //restore cashed QRs / rules
4170
4171 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
4172 // {
4173 // quest_rules[q] = cached_rules[q];
4174 // }
4175 }
4176
4177 static char bitstrbuf[32];
4178 bool leeching_from_tiles=false;
4179
4180 const char *bitlist(int32_t index, int32_t *list_size)
4181 {
4182 int32_t imported=2;
4183
4184 if(index>=0)
4185 {
4186 bound(index,0,leeching_from_tiles?2:1);
4187
4188 if(index==imported)
4189 {
4190 sprintf(bitstrbuf,"Imported");
4191 }
4192 else
4193 {
4194 sprintf(bitstrbuf,"%d",4<<index);
4195 }
4196
4197 return bitstrbuf;
4198 }
4199
4200 *list_size=leeching_from_tiles?3:2;
4201 return NULL;
4202 }
4203
4204 8 static ListData bit_list(bitlist, &font);
4205
4206 static DIALOG leech_dlg[] =
4207 {
4208 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
4209 8 { jwin_win_proc, 8, 20-4, 303+1, 216-42+1, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Leech Options", NULL, NULL },
4210 8 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
4211 // 2
4212 8 { jwin_button_proc, 180, 210-42-4, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
4213 8 { jwin_button_proc, 80, 210-42-4, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
4214 8 { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL },
4215 // 5
4216 8 { jwin_text_proc, 14, 49-4, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Update Status Every: ", NULL, NULL },
4217 8 { jwin_edit_proc, 114, 45-4, 36, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL },
4218 8 { jwin_radio_proc, 155, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Tiles", NULL, NULL },
4219 8 { jwin_radio_proc, 200, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Seconds", NULL, NULL },
4220 //9
4221 8 { jwin_frame_proc, 14, 63-2, 176+70, 50+30, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL },
4222 8 { jwin_text_proc, 14+8, 60-2, 80, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) " Duplicates ", NULL, NULL },
4223
4224 8 { jwin_check_proc, 20, 70, 168, 8+1, vc(15), vc(1), 0, 0, 1, 0, (void *) "Only check new tiles", NULL, NULL },
4225 8 { jwin_text_proc, 20, 90, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Normal:", NULL, NULL },
4226 8 { jwin_text_proc, 20, 100, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal Flip:", NULL, NULL },
4227 8 { jwin_text_proc, 20, 110, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Vertical Flip:", NULL, NULL },
4228 8 { jwin_text_proc, 20, 120, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal/Vertical Flip:", NULL, NULL },
4229 //16
4230 8 { jwin_radio_proc, 144, 90, 64+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4231 8 { jwin_radio_proc, 184, 90, 56+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4232 8 { jwin_radio_proc, 224, 90, 72+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4233
4234 8 { jwin_radio_proc, 144, 100, 64+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4235 8 { jwin_radio_proc, 184, 100, 56+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4236 8 { jwin_radio_proc, 224, 100, 72+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4237
4238 8 { jwin_radio_proc, 144, 110, 64+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4239 8 { jwin_radio_proc, 184, 110, 56+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4240 8 { jwin_radio_proc, 224, 110, 72+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4241
4242 8 { jwin_radio_proc, 144, 120, 64+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4243 8 { jwin_radio_proc, 184, 120, 56+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4244 8 { jwin_radio_proc, 224, 120, 72+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4245
4246 8 { jwin_ctext_proc, 144+4, 80, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Ignore", NULL, NULL },
4247 8 { jwin_ctext_proc, 184+4, 80, 56+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Check", NULL, NULL },
4248 8 { jwin_ctext_proc, 224+4, 80, 72+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Discard", NULL, NULL },
4249 8 { jwin_droplist_proc, 76, 145, 80, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &bit_list, NULL, NULL },
4250 8 { jwin_text_proc, 14, 149, 60, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Color Depth: ", NULL, NULL },
4251 8 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
4252 };
4253
4254 bool leech_tiles(tiledata *dest,int32_t start,int32_t cs)
4255 {
4256 bool shift=true; // fix this!
4257 int32_t cst=0;
4258 int32_t currtile=start;
4259 int32_t height=0, width=0;
4260 byte *testtile = new byte[tilesize(tf32Bit)];
4261 byte imported_format=0;
4262 char updatestring[6];
4263 bool canadd;
4264 bool temp_canadd;
4265 bool duplicate;
4266 int32_t total_duplicates_found=0, total_duplicates_discarded=0;
4267 int32_t duplicates_found[4]= //, duplicates_discarded[4]={0,0,0,0};
4268 {
4269 0,0,0,0
4270 };
4271 BITMAP *status;
4272 status = create_bitmap_ex(8,240,140);
4273 clear_bitmap(status);
4274 sprintf(updatestring, "%d", LeechUpdate);
4275 leech_dlg[0].dp2=get_zc_font(font_lfont);
4276 leech_dlg[6].dp=updatestring;
4277
4278 leech_dlg[10].flags=(OnlyCheckNewTilesForDuplicates!=0) ? D_SELECTED : 0;
4279
4280 for(int32_t i=0; i<2; i++)
4281 {
4282 leech_dlg[i+7].flags=0;
4283 }
4284
4285 leech_dlg[7+((LeechUpdateTiles==0) ? 1 : 0)].flags=D_SELECTED;
4286
4287 for(int32_t i=0; i<12; i++)
4288 {
4289 leech_dlg[i+16].flags=0;
4290 }
4291
4292 for(int32_t i=0; i<4; i++)
4293 {
4294 leech_dlg[(DuplicateAction[i])+16+(i*3)].flags=D_SELECTED;
4295 }
4296
4297 leech_dlg[31].d1=0;
4298
4299 large_dialog(leech_dlg);
4300
4301 int32_t ret = do_zqdialog(leech_dlg,3);
4302
4303 if(ret==2)
4304 {
4305 delete[] testtile;
4306 return false;
4307 }
4308
4309 int32_t cdepth=leech_dlg[31].d1+1;
4310 int32_t newformat=0;
4311 auto lu = atoi(updatestring);
4312 auto lut = (leech_dlg[7].flags&D_SELECTED)?1:0;
4313 if(LeechUpdate!=lu)
4314 {
4315 LeechUpdate=lu;
4316 zc_set_config("zquest","leech_update",LeechUpdate);
4317 }
4318 if(LeechUpdateTiles!=lut)
4319 {
4320 LeechUpdateTiles=lut;
4321 zc_set_config("zquest","leech_update_tiles",LeechUpdateTiles);
4322 }
4323
4324 int32_t old_dupe[4];
4325 for(int32_t j=0; j<4; j++)
4326 {
4327 old_dupe[j] = DuplicateAction[j];
4328 for(int32_t i=0; i<3; i++)
4329 {
4330 if(leech_dlg[i+16+(j*3)].flags&D_SELECTED)
4331 {
4332 DuplicateAction[j]=i;
4333 }
4334 }
4335 }
4336 if(old_dupe[0] != DuplicateAction[0])
4337 zc_set_config("zquest","normal_duplicate_action",DuplicateAction[0]);
4338 if(old_dupe[1] != DuplicateAction[1])
4339 zc_set_config("zquest","horizontal_duplicate_action",DuplicateAction[1]);
4340 if(old_dupe[2] != DuplicateAction[2])
4341 zc_set_config("zquest","vertical_duplicate_action",DuplicateAction[2]);
4342 if(old_dupe[3] != DuplicateAction[3])
4343 zc_set_config("zquest","both_duplicate_action",DuplicateAction[3]);
4344
4345 auto ocntfd = leech_dlg[10].flags&D_SELECTED?1:0;
4346 if(OnlyCheckNewTilesForDuplicates!=ocntfd)
4347 {
4348 OnlyCheckNewTilesForDuplicates=ocntfd;
4349 zc_set_config("zquest","only_check_new_tiles_for_duplicates",ocntfd);
4350 }
4351
4352 leeching_from_tiles=false;
4353
4354 switch(imagetype)
4355 {
4356 case ftBIN:
4357 width=imagesize/128;
4358 height=1;
4359 break;
4360
4361 case ftZGP:
4362 case ftQST:
4363 case ftZQT:
4364 case ftQSU:
4365 case ftTIL:
4366 leeching_from_tiles=true;
4367 width=count_tiles(grabtilebuf);
4368 height=1;
4369 break;
4370
4371 case ftBMP:
4372 width=((((BITMAP*)imagebuf)->w)+15)/16;
4373 height=((((BITMAP*)imagebuf)->h)+15)/16;
4374 break;
4375 }
4376
4377 if(currtile+(width*height)>NEWMAXTILES)
4378 {
4379 if(jwin_alert("Confirm Truncation","Too many tiles.","Truncation may occur.",NULL,"&OK","&Cancel",'o','c',get_zc_font(font_lfont))==2)
4380 {
4381 delete[] testtile;
4382 return false;
4383 }
4384 }
4385
4386 go_tiles();
4387 saved=false;
4388
4389 // usetiles=true;
4390 for(int32_t ty=0; ty<height; ty++) //for every row
4391 {
4392 for(int32_t tx=0; tx<width; tx++) //for every column (tile)
4393 {
4394 if((((ty*width)+tx)%zc_max(LeechUpdate, 1))==0) //update status
4395 {
4396 FONT *oldfont = font;
4397 static BITMAP *tbar = create_bitmap_ex(8,240-6, 18);
4398 static bool created_tbar=false;
4399 jwin_draw_win(status, 0, 0, 240, 140, FR_WIN);
4400
4401 if(created_tbar)
4402 {
4403 blit(tbar, status, 0, 0, 3, 3, 240-6, 18);
4404 }
4405 else
4406 {
4407 font = get_zc_font(font_lfont);
4408 jwin_draw_titlebar(tbar, 0, 0, 240-6, 18, "Leech Status", false);
4409 font = oldfont;
4410 created_tbar=true;
4411 blit(tbar, status, 0, 0, 3, 3, 320-6, 18);
4412 }
4413
4414 textprintf_centre_ex(status,font,120,24,jwin_pal[jcTEXTFG],-1,"Checking %d of %d",((ty*width)+tx), (width*height));
4415 textprintf_centre_ex(status,font,120,34,jwin_pal[jcTEXTFG],-1,"%d tiles imported",currtile-start);
4416 jwin_draw_frame(status, 40, 49, 160, 70, FR_ETCHED);
4417 textprintf_centre_ex(status,font,120,46,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]," Duplicates ");
4418 textprintf_centre_ex(status,font,120,56,jwin_pal[jcTEXTFG],-1,"%d/%d found/discarded",total_duplicates_found, total_duplicates_discarded);
4419 textprintf_centre_ex(status,font,120,76,jwin_pal[jcTEXTFG],-1,"%d normal %s",duplicates_found[0],((DuplicateAction[0]<2)?"found":"discarded"));
4420 textprintf_centre_ex(status,font,120,86,jwin_pal[jcTEXTFG],-1,"%d flipped (h) %s",duplicates_found[1],((DuplicateAction[1]<2)?"found":"discarded"));
4421 textprintf_centre_ex(status,font,120,96,jwin_pal[jcTEXTFG],-1,"%d flipped (v) %s",duplicates_found[2],((DuplicateAction[2]<2)?"found":"discarded"));
4422 textprintf_centre_ex(status,font,120,106,jwin_pal[jcTEXTFG],-1,"%d flipped (hv) %s",duplicates_found[3],((DuplicateAction[3]<2)?"found":"discarded"));
4423 textprintf_centre_ex(status,font,120,128,jwin_pal[jcTEXTFG],-1,"Press any key to stop.");
4424 blit(status,screen,0, 0, 40, 20, 240, 140);
4425 SCRFIX();
4426 }
4427
4428 canadd=true;
4429
4430 if(currtile>=NEWMAXTILES) //if we've maxed out on our tiles...
4431 {
4432 delete[] testtile;
4433 return true;
4434 }
4435
4436 switch(imagetype)
4437 {
4438 case ftBIN:
4439 break;
4440
4441 case ftZGP:
4442 case ftQST:
4443 case ftZQT:
4444 case ftQSU:
4445 case ftTIL:
4446 memset(testtile, 0, tilesize(tf32Bit));
4447 imported_format=grabtilebuf[tx].format;
4448
4449 switch(cdepth)
4450 {
4451 case 1: //4-bit
4452 newformat=tf4Bit;
4453
4454 switch(imported_format)
4455 {
4456 case tf4Bit:
4457 case tf8Bit:
4458 for(int32_t y=0; y<16; y++) //snag a tile
4459 {
4460 for(int32_t x=0; x<16; x+=2)
4461 {
4462 testtile[(y*8)+(x/2)]=
4463 (grabtilebuf[tx].data[y*16+x]&15)+
4464 ((grabtilebuf[tx].data[y*16+x+1]&15)<<4);
4465 }
4466 }
4467
4468 break;
4469 }
4470
4471 break;
4472
4473 case 2: //8-bit
4474 newformat=tf8Bit;
4475
4476 switch(imported_format)
4477 {
4478 case tf4Bit:
4479 unpack_tile(grabtilebuf, tx, 0, true);
4480 cst = cs&15;
4481 cst <<= CSET_SHFT;
4482
4483 for(int32_t i=0; i<256; i++)
4484 {
4485 if(!shift||unpackbuf[i]!=0)
4486 {
4487 unpackbuf[i]+=cst;
4488 }
4489 }
4490
4491 pack_tiledata(testtile, unpackbuf, tf8Bit);
4492 break;
4493
4494 case tf8Bit:
4495 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4496 break;
4497 }
4498
4499 break;
4500
4501 case 3: //original tile's bit depth
4502 newformat=imported_format;
4503 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4504 break;
4505 }
4506
4507 break;
4508
4509 case ftBMP:
4510 newformat=cdepth;
4511
4512 for(int32_t y=0; y<16; y++) //snag a tile
4513 {
4514 for(int32_t x=0; x<16; x+=2)
4515 {
4516 testtile[(y*16)+x]=getpixel(((BITMAP*)imagebuf),(tx*16)+x,(ty*16)+y);
4517 testtile[(y*16)+x+1]=getpixel(((BITMAP*)imagebuf),(tx*16)+x+1,(ty*16)+y);
4518 }
4519 }
4520
4521 break;
4522 }
4523
4524 if(DuplicateAction[0]+DuplicateAction[1]+DuplicateAction[2]+DuplicateAction[3]>0)
4525 {
4526 temp_canadd=true;
4527
4528 //check all tiles before this one
4529 for(int32_t checktile=((OnlyCheckNewTilesForDuplicates!=0)?start:0); ((temp_canadd==true)&&(checktile<currtile)); checktile++)
4530 {
4531 for(int32_t flipping=0; ((temp_canadd==true)&&(flipping<4)); ++flipping)
4532 {
4533 if(DuplicateAction[flipping]>0)
4534 {
4535 if(keypressed())
4536 {
4537 delete[] testtile;
4538 return true;
4539 }
4540
4541 duplicate=(newformat==imported_format);
4542
4543 if(duplicate)
4544 {
4545 switch(flipping)
4546 {
4547 case 0: //normal
4548 if(dest[checktile].data!=NULL)
4549 {
4550 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4551 {
4552 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4553 {
4554 // if ((dest[(checktile*128)+(y*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4555 if((dest[checktile].data[(y*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4556 {
4557 duplicate=false;
4558 }
4559 }
4560 }
4561 }
4562
4563 break;
4564
4565 case 1: //horizontal
4566 if(dest[checktile].data!=NULL)
4567 {
4568 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4569 {
4570 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4571 {
4572 // if ((dest[(checktile*128)+(y*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4573 if((dest[checktile].data[(y*8*newformat)+(14+(newformat-1)-x)/(3-newformat)])!=testtile[(y*16)+x])
4574 {
4575 duplicate=false;
4576 }
4577 }
4578 }
4579 }
4580
4581 break;
4582
4583 case 2: //vertical
4584 if(dest[checktile].data!=NULL)
4585 {
4586 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4587 {
4588 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4589 {
4590 // if ((dest[(checktile*128)+((15-y)*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4591 if((dest[checktile].data[((15-y)*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4592 {
4593 duplicate=false;
4594 }
4595 }
4596 }
4597 }
4598
4599 break;
4600
4601 case 3: //both
4602 if(dest[checktile].data!=NULL)
4603 {
4604 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4605 {
4606 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4607 {
4608 // if ((dest[(checktile*128)+((15-y)*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4609 if((dest[checktile].data[((15-y)*8*newformat)+((14+(newformat-1)-x)/(3-newformat))])!=testtile[(y*16)+x])
4610 {
4611 duplicate=false;
4612 }
4613 }
4614 }
4615 }
4616
4617 break;
4618 }
4619 }
4620
4621 if(duplicate==true)
4622 {
4623 ++duplicates_found[flipping];
4624 ++total_duplicates_found;
4625
4626 if(DuplicateAction[flipping]>1)
4627 {
4628 ++total_duplicates_discarded;
4629 temp_canadd=false;
4630 }
4631 }
4632 }
4633
4634 canadd=canadd&&temp_canadd;
4635 }
4636 }
4637 }
4638
4639 // dest[currtile].format=(cdepth==3?imported_format:cdepth);
4640 dest[currtile].format=newformat;
4641
4642 if(dest[currtile].data!=NULL)
4643 {
4644 free(dest[currtile].data);
4645 }
4646
4647 dest[currtile].data=(byte *)malloc(tilesize(dest[currtile].format));
4648
4649 if(dest[currtile].data==NULL)
4650 {
4651 Z_error_fatal("Unable to initialize tile #%d.\n", currtile);
4652 }
4653
4654 if(canadd==true)
4655 {
4656 /*
4657 for(int32_t y=0; y<16; y++)
4658 {
4659 for(int32_t x=0; x<8; x++)
4660 {
4661 dest[currtile].data[(y*8)+x]=testtile[(y*8)+x];
4662 }
4663 }
4664 */
4665 memcpy(dest[currtile].data, testtile, tilesize(dest[currtile].format));
4666 ++currtile;
4667 }
4668 }
4669 }
4670
4671 destroy_bitmap(status);
4672 delete[] testtile;
4673 return true;
4674 }
4675
4676 void grab(byte(*dest)[256],byte *def, int32_t width, int32_t height, int32_t oformat, byte *newformat)
4677 {
4678 byte defFormat=(bp==8) ? tf8Bit : tf4Bit;
4679 byte format=defFormat;
4680 int32_t stile = ((imagey*TILES_PER_ROW)+imagex)+(((sely/16)*TILES_PER_ROW)+(selx/16));
4681
4682 switch(imagetype)
4683 {
4684 case ftZGP:
4685 case ftQST:
4686 case ftZQT:
4687 case ftQSU:
4688 case ftTIL:
4689 case ftBIN:
4690 case ftBMP:
4691 for(int32_t ty=0; ty<height; ty++)
4692 {
4693 for(int32_t tx=0; tx<width; tx++)
4694 {
4695 format=defFormat;
4696 switch(imagetype)
4697 {
4698 case ftZGP:
4699 case ftQST:
4700 case ftZQT:
4701 case ftQSU:
4702 case ftTIL:
4703 format=grabtilebuf[stile+((ty*TILES_PER_ROW)+tx)].format;
4704 break;
4705 }
4706
4707 bool ever_did_unmasked = false;
4708
4709 for(int32_t y=0; y<16; y++)
4710 {
4711 for(int32_t x=0; x<16; x+=2)
4712 {
4713 bool masked = (y<8 && x<8 && grabmask&1) || (y<8 && x>7 && grabmask&2) || (y>7 && x<8 && grabmask&4) || (y>7 && x>7 && grabmask&8);
4714 if (masked)
4715 {
4716 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x)]=def[(y*16)+(x)];
4717 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x+1)]=def[(y*16)+(x+1)];
4718 }
4719 else
4720 {
4721 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x]=getpixel(screen2,(tx*16)+x+selx,(ty*16)+y+sely);
4722 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1]=getpixel(screen2,(tx*16)+x+1+selx,(ty*16)+y+sely);
4723 ever_did_unmasked = true;
4724 }
4725 if (format == tf4Bit)
4726 {
4727 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x] &= 15;
4728 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1] &= 15;
4729 }
4730 }
4731 }
4732
4733 if (ever_did_unmasked)
4734 newformat[(ty*TILES_PER_ROW)+tx] = format;
4735 }
4736 }
4737
4738 break;
4739
4740 default:
4741 for(int32_t i=0; i<200; i++)
4742 {
4743 for(int32_t j=0; j<256; j++)
4744 {
4745 dest[i][j]=0;
4746 }
4747
4748 newformat[i] = tf4Bit;
4749 }
4750
4751 break;
4752 }
4753 }
4754
4755 static void scale_imagebuf_bitmap()
4756 {
4757 imagebuf_bitmap_scale = std::clamp(imagebuf_bitmap_scale, -10, 10);
4758
4759 float scale = IMAGEBUF_SCALE;
4760 int nw = original_imagebuf_bitmap->w * scale;
4761 int nh = original_imagebuf_bitmap->h * scale;
4762 if (nw <= 0 || nh <= 0)
4763 return;
4764
4765 BITMAP* scaled_bmp = create_bitmap_ex(8, nw, nh);
4766 if (!scaled_bmp)
4767 return;
4768
4769 stretch_blit(original_imagebuf_bitmap, scaled_bmp, 0, 0, original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, 0, 0, nw, nh);
4770 if (imagebuf != original_imagebuf_bitmap)
4771 destroy_bitmap((BITMAP*)imagebuf);
4772 imagebuf = scaled_bmp;
4773 }
4774
4775 //Grabber is not grabbing to tile pages beyond pg. 252 right now. -ZX 18th June, 2019
4776 void grab_tile(int32_t tile,int32_t &cs)
4777 {
4778 zq_allow_tile_draw_cache = true;
4779
4780 int window_w = 640+6+6, window_h = 480+25+6;
4781 int window_x=(zq_screen_w-window_w)/2;
4782 int window_y=(zq_screen_h-window_h)/2;
4783 popup_zqdialog_start(window_x,window_y,window_w,window_h,-1);
4784 int window_xofs = 0;
4785 int screen_xofs=6;
4786 int screen_yofs=25;
4787 int panel_yofs=0;
4788 int bwidth = 61*1.5;
4789 int bheight = 20*1.5;
4790 int button_x = 255*2;
4791 int grab_ok_button_y = 168*2 + 32;
4792 int leech_button_x = 117*2;
4793 int leech_button_y = 166*2 + 32;
4794 int grab_cancel_button_y = 192*2 + 32;
4795 int file_button_y = 216*2 + 32;
4796 int rec_button_x = 117*2;
4797 int rec_button_y = 192*2 + 32;
4798
4799 int screen_y1 = 24;
4800 int screen_y2 = screen_y1+320-1;
4801
4802 int crect_x = 184+190;
4803 int crect_y = 168*2 + 32;
4804 int crect_w = 8*2;
4805 int crect_h = 8*2;
4806
4807 int xrect_x = 640 + 12 - 21;
4808 int xrect_y = 5;
4809
4810 byte newtile[200][256];
4811 BITMAP *screen3=create_bitmap_ex(8, zq_screen_w, zq_screen_h);
4812 clear_bitmap(screen3);
4813 byte newformat[200];
4814
4815 memset(newtile, 0, 200*256);
4816 memset(newformat, 0, 200);
4817
4818 static EXT_LIST list[] =
4819 {
4820 { (char *)"All Files (*.*)", NULL },
4821 { (char *)"Bitmap Image (*.bmp)", (char *)"bmp" },
4822 { (char *)"GIF Image (*.gif)", (char *)"gif" },
4823 { (char *)"JPEG Image (*.jpg, *.jpeg)", (char *)"jpg,jpeg" },
4824 { (char *)"ZC Tile Export (*.til)", (char *)"til" },
4825 { (char *)"ZC Quest Template (*.zqt)", (char *)"zqt" },
4826 { (char *)"ZC Quest (*.qst)", (char *)"qst" },
4827 { (char *)"ZC Graphics Pack (*.zgp)", (char *)"zgp" },
4828 { (char *)"ZC Unencoded Quest (*.qsu)", (char *)"qsu" },
4829 { (char *)"NES ROM Image (*.nes)", (char *)"nes" },
4830 { (char *)"SNES ROM Image (*.smc)", (char *)"smc" },
4831 { (char *)"Gameboy ROM Image (*.gb)", (char *)"gb" },
4832 { (char *)"Gameboy Advance ROM Image (*.gba)", (char *)"gba" },
4833 { NULL, NULL }
4834 };
4835
4836
4837 memset(cset_reduce_table, 0, 256);
4838 memset(col_diff,0,3*128);
4839 bool bdown=false;
4840 int done=0;
4841 int pal=0;
4842 int f=0;
4843 int black=vc(0),white=vc(15);
4844 int selwidth=1, selheight=1;
4845 int selx2=0, sely2=0;
4846 bool xreversed=false, yreversed=false;
4847 bool doleech=false, dofile=false, dopal=false;
4848
4849 int jwin_pal2[jcMAX];
4850 memcpy(jwin_pal2, jwin_pal, sizeof(int)*jcMAX);
4851
4852
4853 if(imagebuf==NULL)
4854 load_imagebuf();
4855
4856 calc_cset_reduce_table(imagepal, cs);
4857 calc_cset_reduce_table_8bit(imagepal);
4858 draw_grab_window();
4859 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
4860 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
4861
4862 while(gui_mouse_b())
4863 {
4864 /* do nothing */
4865 rest(1);
4866 }
4867
4868 do
4869 {
4870 HANDLE_CLOSE_ZQDLG();
4871 if(exiting_program) break;
4872 rest(4);
4873 bool redraw=false;
4874
4875 if(keypressed())
4876 {
4877 redraw=true;
4878
4879 switch(readkey()>>8)
4880 {
4881 case KEY_F:
4882 dofile=true;
4883 break;
4884
4885 case KEY_L:
4886 doleech=true;
4887 break;
4888
4889 case KEY_P:
4890 if(imagetype==ftBMP)
4891 {
4892 dopal=true;
4893 recolor=rcNone;
4894 calc_cset_reduce_table(imagepal, cs);
4895 }
4896
4897 break;
4898
4899 case KEY_ESC:
4900 done=1;
4901 break;
4902
4903 case KEY_ENTER_PAD:
4904 case KEY_ENTER:
4905 done=2;
4906 break;
4907
4908 case KEY_DOWN:
4909 if(CHECK_CTRL_CMD) sely=zc_min(sely+1,144);
4910 else ++imagey;
4911
4912 break;
4913
4914 case KEY_UP:
4915 if(CHECK_CTRL_CMD) sely=zc_max(sely-1,0);
4916 else --imagey;
4917
4918 break;
4919
4920 case KEY_RIGHT:
4921 if(CHECK_CTRL_CMD) selx=zc_min(selx+1,304);
4922 else ++imagex;
4923
4924 break;
4925
4926 case KEY_LEFT:
4927 if(CHECK_CTRL_CMD) selx=zc_max(selx-1,0);
4928 else --imagex;
4929
4930 break;
4931
4932 case KEY_PGDN:
4933 imagey+=10;
4934 break;
4935
4936 case KEY_PGUP:
4937 imagey-=10;
4938 break;
4939
4940 case KEY_HOME:
4941 imagex=imagey=0;
4942 break;
4943
4944 case KEY_EQUALS:
4945 case KEY_PLUS_PAD:
4946 cs = (cs<13) ? cs+1:0;
4947 if(recolor==rc4Bit)
4948 calc_cset_reduce_table(imagepal, cs);
4949 break;
4950
4951 case KEY_MINUS:
4952 case KEY_MINUS_PAD:
4953 cs = (cs>0) ? cs-1:13;
4954 if(recolor==rc4Bit)
4955 calc_cset_reduce_table(imagepal, cs);
4956 break;
4957
4958 case KEY_S:
4959 if(grabmode==1) grabmode=8;
4960 else if(grabmode==8) grabmode=16;
4961 else grabmode=1;
4962
4963 break;
4964
4965 case KEY_COMMA:
4966 if (imagetype == ftBMP)
4967 {
4968 imagebuf_bitmap_scale--;
4969 if (imagebuf_bitmap_scale == 0)
4970 imagebuf_bitmap_scale = -2;
4971 scale_imagebuf_bitmap();
4972 }
4973 break;
4974 case KEY_STOP:
4975 if (imagetype == ftBMP)
4976 {
4977 imagebuf_bitmap_scale++;
4978 if (imagebuf_bitmap_scale == -1)
4979 imagebuf_bitmap_scale = 1;
4980 scale_imagebuf_bitmap();
4981 }
4982 break;
4983
4984 case KEY_1:
4985 if(recolor==rc8Bit)
4986 recolor=rcNone;
4987 //imagex=(imagex*bp)>>3;
4988 bp=1;
4989 //imagex<<=3;
4990 nesmode=false;
4991 break;
4992
4993 case KEY_2:
4994 if(recolor==rc8Bit)
4995 recolor=rcNone;
4996 //imagex=(imagex*bp)>>3;
4997 bp=2;
4998 //imagex<<=2;
4999 nesmode=false;
5000 break;
5001
5002 case KEY_N:
5003 if(recolor==rc8Bit)
5004 recolor=rcNone;
5005 //imagex=(imagex*bp)>>3;
5006 bp=2;
5007 //imagex<<=2;
5008 nesmode=true;
5009 break;
5010
5011 case KEY_4:
5012 if(recolor==rc8Bit)
5013 recolor=rcNone;
5014 //imagex=(imagex*bp)>>3;
5015 bp=4;
5016 //imagex<<=1;
5017 nesmode=false;
5018 break;
5019
5020 case KEY_8:
5021 //imagex=(imagex*bp)>>3;
5022 bp=8;
5023 break;
5024
5025 case KEY_B:
5026 if(bp==2&&!nesmode)
5027 {
5028 nesmode=true;
5029 }
5030 else
5031 {
5032 nesmode=false;
5033 bp<<=1;
5034
5035 if(bp==16)
5036 {
5037 bp=1;
5038 //imagex<<=3;
5039 }
5040 else
5041 {
5042 //imagex>>=1;
5043 }
5044 }
5045
5046 break;
5047
5048 case KEY_M:
5049 romtilemode=(romtilemode+1)%4;
5050 break;
5051
5052 case KEY_Z:
5053 if(romofs>0) --romofs;
5054
5055 break;
5056
5057 case KEY_X:
5058 ++romofs;
5059 break;
5060
5061 case KEY_R:
5062 if(pal)
5063 {
5064 dopal=true;
5065 }
5066
5067 if(recolor!=rcNone)
5068 recolor=rcNone;
5069 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5070 {
5071 bp=8;
5072 recolor=rc8Bit;
5073 calc_cset_reduce_table_8bit(imagepal);
5074 }
5075 else
5076 {
5077 if(bp==8)
5078 bp=4;
5079 recolor=rc4Bit;
5080 calc_cset_reduce_table(imagepal, cs);
5081 }
5082 break;
5083
5084 default:
5085 redraw=false;
5086 }
5087
5088 clear_keybuf();
5089
5090 if(imagex<0) imagex=0;
5091
5092 if(imagey<0) imagey=0;
5093
5094 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5095 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5096 }
5097
5098 //boogie!
5099 if(gui_mouse_b()==1 && !bdown)
5100 {
5101 int x=gui_mouse_x();
5102 int y=gui_mouse_y();
5103 if(isinRect(x,y,xrect_x, xrect_y, xrect_x + 15, xrect_y + 13))
5104 if(do_x_button(screen, xrect_x, xrect_y))
5105 done=1;
5106
5107 if(!bdown)
5108 {
5109 bool regrab=false;
5110 bdown=true;
5111 FONT* oldfont = font;
5112 font = get_zc_font(font_lfont_l);
5113
5114 if(y>=screen_y1 && y<=screen_y2)
5115 {
5116 do
5117 {
5118 HANDLE_CLOSE_ZQDLG();
5119 if(exiting_program) break;
5120 int x = (gui_mouse_x()-screen_xofs) / 2;
5121 int y = (gui_mouse_y()-screen_yofs) / 2;
5122
5123 int ox=selx,oy=sely,ow=selwidth,oh=selheight;
5124
5125 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
5126 {
5127 selx=vbound((x/grabmode)*grabmode,0,304);
5128 sely=vbound((y/grabmode)*grabmode,0,144);
5129 selx2=selx;
5130 sely2=sely;
5131 selwidth=1;
5132 selheight=1;
5133 xreversed=false;
5134 yreversed=false;
5135 }
5136 else
5137 {
5138 if(xreversed)
5139 {
5140 zc_swap(selx, selx2);
5141 xreversed=false;
5142 }
5143
5144 if(yreversed)
5145 {
5146 zc_swap(sely, sely2);
5147 yreversed=false;
5148 }
5149
5150 selx2=vbound((x/grabmode)*grabmode,0,304);
5151 sely2=vbound((y/grabmode)*grabmode,0,144);
5152 selwidth=1+(abs(selx2-selx))/16;
5153 selheight=1+(abs(sely2-sely))/16;
5154
5155 if(selx2<selx)
5156 {
5157 zc_swap(selx, selx2);
5158 xreversed=true;
5159 }
5160
5161 if(sely2<sely)
5162 {
5163 zc_swap(sely, sely2);
5164 yreversed=true;
5165 }
5166 }
5167
5168 bool changed = (ox!=selx || oy!=sely || ow!=selwidth || oh!=selheight);
5169 bool redraw = changed || !(f%8);
5170
5171 if(redraw)
5172 {
5173 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5174 if(changed)
5175 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5176 if(f&8)
5177 {
5178 static const int w = 32;
5179 rect(screen,(selx*2)+screen_xofs,(sely*2)+screen_yofs,(selx*2)+screen_xofs+((selwidth-1)*w)+(w-1),(sely*2)+screen_yofs+((selheight-1)*w)+(w-1),white);
5180 }
5181 }
5182 else custom_vsync();
5183
5184 ++f;
5185 }
5186 while(gui_mouse_b());
5187 }
5188 else if(isinRect(x,y,button_x,grab_ok_button_y,button_x+bwidth,grab_ok_button_y+bheight))
5189 {
5190 if(do_text_button(button_x,grab_ok_button_y,bwidth,bheight,"OK"))
5191 done=2;
5192 }
5193 else if(isinRect(x,y,leech_button_x,leech_button_y,leech_button_x+bwidth,leech_button_y+bheight))
5194 {
5195 if(do_text_button(leech_button_x,leech_button_y,bwidth,bheight,"Leech"))
5196 {
5197 doleech=true;
5198 }
5199 }
5200 else if(isinRect(x,y,button_x,grab_cancel_button_y,button_x+bwidth,grab_cancel_button_y+bheight))
5201 {
5202 if(do_text_button(button_x,grab_cancel_button_y,bwidth,bheight,"Cancel"))
5203 done=1;
5204 }
5205 else if(isinRect(x,y,button_x,file_button_y,button_x+bwidth,file_button_y+bheight))
5206 {
5207 if(do_text_button(button_x,file_button_y,bwidth,bheight,"File"))
5208 {
5209 dofile=true;
5210 }
5211 }
5212 else if(imagetype == ftBMP && isinRect(x,y,rec_button_x, rec_button_y, rec_button_x+bwidth, rec_button_y+bheight))
5213 {
5214 if(do_text_button(rec_button_x,rec_button_y,bwidth,bheight,"Recolor"))
5215 {
5216 if(pal)
5217 {
5218 dopal = true;
5219 }
5220
5221 if(recolor!=rcNone)
5222 recolor=rcNone;
5223 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5224 {
5225 bp=8;
5226 recolor=rc8Bit;
5227 calc_cset_reduce_table_8bit(imagepal);
5228 }
5229 else
5230 {
5231 if(bp==8)
5232 bp=4;
5233 recolor=rc4Bit;
5234 calc_cset_reduce_table(imagepal, cs);
5235 }
5236 redraw=true;
5237 }
5238 }
5239 else if(isinRect(x,y+panel_yofs,crect_x,crect_y,crect_x+(16),crect_y+crect_h-1))
5240 {
5241 regrab=true;
5242 grabmask^=1;
5243 }
5244 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y,crect_x+(32)-1,crect_y+crect_h-1))
5245 {
5246 regrab=true;
5247 grabmask^=2;
5248 }
5249 else if(isinRect(x,y+panel_yofs,crect_x,crect_y+crect_h,crect_x+(16)-1,crect_y+crect_h+crect_h-1))
5250 {
5251 regrab=true;
5252 grabmask^=4;
5253 }
5254 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y+crect_h,crect_x+(32)-1,crect_y+crect_h+crect_h-1))
5255 {
5256 regrab=true;
5257 grabmask^=8;
5258 }
5259
5260 if(regrab)
5261 {
5262 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5263 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5264 redraw=true;
5265 }
5266
5267 font = oldfont;
5268 }
5269 }
5270
5271 if(gui_mouse_b()==0)
5272 bdown=false;
5273
5274 if(dofile)
5275 {
5276
5277 if(getname_nogo("Load File",NULL,list,imagepath,true))
5278 {
5279 zc_set_palette(RAMpal);
5280 pal=0;
5281 white=vc(15);
5282 black=vc(0);
5283 strcpy(imagepath,temppath);
5284 load_imagebuf();
5285 imagex=imagey=0;
5286 calc_cset_reduce_table(imagepal, cs);
5287 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5288 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5289 }
5290
5291 while(key[KEY_ESC])
5292 {
5293 poll_keyboard();
5294 /* do nothing */
5295 rest(1);
5296 }
5297
5298 clear_keybuf();
5299 dofile=false;
5300 redraw=true;
5301 }
5302
5303 if(doleech)
5304 {
5305 if(leech_tiles(newtilebuf,tile,cs))
5306 {
5307 done=1;
5308 }
5309 else
5310 {
5311 while(key[KEY_ESC])
5312 {
5313 poll_keyboard();
5314 /* do nothing */
5315 rest(1);
5316 }
5317
5318 clear_keybuf();
5319 redraw=true;
5320 }
5321
5322 doleech=false;
5323 }
5324
5325 if(dopal)
5326 {
5327 pal^=1;
5328
5329 if(pal)
5330 {
5331 get_bw(imagepal,black,white);
5332
5333 jwin_pal[jcBOX] =imagepal_table.data[0][jwin_pal[jcBOX]];
5334 jwin_pal[jcLIGHT] =imagepal_table.data[0][jwin_pal[jcLIGHT]];
5335 jwin_pal[jcMEDLT] =imagepal_table.data[0][jwin_pal[jcMEDLT]];
5336 jwin_pal[jcMEDDARK]=imagepal_table.data[0][jwin_pal[jcMEDDARK]];
5337 jwin_pal[jcDARK] =imagepal_table.data[0][jwin_pal[jcDARK]];
5338 jwin_pal[jcBOXFG] =imagepal_table.data[0][jwin_pal[jcBOXFG]];
5339 jwin_pal[jcTITLEL] =imagepal_table.data[0][jwin_pal[jcTITLEL]];
5340 jwin_pal[jcTITLER] =imagepal_table.data[0][jwin_pal[jcTITLER]];
5341 jwin_pal[jcTITLEFG]=imagepal_table.data[0][jwin_pal[jcTITLEFG]];
5342 jwin_pal[jcTEXTBG] =imagepal_table.data[0][jwin_pal[jcTEXTBG]];
5343 jwin_pal[jcTEXTFG] =imagepal_table.data[0][jwin_pal[jcTEXTFG]];
5344 jwin_pal[jcSELBG] =imagepal_table.data[0][jwin_pal[jcSELBG]];
5345 jwin_pal[jcSELFG] =imagepal_table.data[0][jwin_pal[jcSELFG]];
5346 gui_bg_color=jwin_pal[jcBOX];
5347 gui_fg_color=jwin_pal[jcBOXFG];
5348 jwin_set_colors(jwin_pal);
5349 }
5350 else
5351 {
5352 white=vc(15);
5353 black=vc(0);
5354
5355 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5356 gui_bg_color=jwin_pal[jcBOX];
5357 gui_fg_color=jwin_pal[jcBOXFG];
5358 jwin_set_colors(jwin_pal);
5359 }
5360
5361 zc_set_palette_range(pal?imagepal:RAMpal,0,255,false);
5362
5363 dopal=false;
5364 redraw=true;
5365 }
5366
5367 if(redraw)
5368 {
5369 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5370 }
5371 else
5372 {
5373 custom_vsync();
5374 }
5375
5376 if((f%8)==0)
5377 {
5378 stretch_blit(screen2,screen3,0, 0, zq_screen_w, zq_screen_h, 0, 0, zq_screen_w*2, zq_screen_h*2);
5379
5380 int selxl = selx* 2;
5381 int selyl = sely* 2;
5382 int w = 32;
5383
5384 if(f&8)
5385 rect(screen3,selxl,selyl,selxl+((selwidth-1)*w)+(w-1),selyl+((selheight-1)*w)+(w-1),white);
5386
5387 blit(screen3,screen,selxl,selyl,selxl+screen_xofs,selyl+screen_yofs,selwidth*w,selheight*w);
5388 }
5389
5390 // SCRFIX();
5391 ++f;
5392
5393 }
5394 while(!done);
5395
5396 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5397 gui_bg_color=jwin_pal[jcBOX];
5398 gui_fg_color=jwin_pal[jcBOXFG];
5399 jwin_set_colors(jwin_pal);
5400
5401
5402 if(done==2)
5403 {
5404 go_tiles();
5405 saved=false;
5406
5407 // usetiles=true;
5408 for(int y=0; y<selheight; y++)
5409 {
5410 for(int x=0; x<selwidth; x++)
5411 {
5412 int temptile=tile+((TILES_PER_ROW*y)+x);
5413 int format=(bp==8) ? tf8Bit : tf4Bit;
5414
5415 if(newtilebuf[temptile].data!=NULL)
5416 free(newtilebuf[temptile].data);
5417
5418 newtilebuf[temptile].format=format;
5419 newtilebuf[temptile].data=(byte *)malloc(tilesize(format));
5420
5421 if(newtilebuf[temptile].data==NULL)
5422 {
5423 Z_error_fatal("Unable to initialize tile #%d.\n", temptile);
5424 break;
5425 }
5426
5427 for(int i=0; i<256; i++)
5428 {
5429 // newtilebuf[temptile].data[i] = cset_reduce_table[newtile[(TILES_PER_ROW*y)+x][i]];
5430 newtilebuf[temptile].data[i] = newtile[(TILES_PER_ROW*y)+x][i];
5431 }
5432
5433 // unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
5434 }
5435 }
5436 }
5437
5438 destroy_bitmap(screen3);
5439
5440 if(pal)
5441 zc_set_palette(RAMpal);
5442
5443 recolor=rcNone;
5444 calc_cset_reduce_table(imagepal, cs);
5445 register_blank_tiles();
5446 popup_zqdialog_end();
5447
5448 zq_allow_tile_draw_cache = false;
5449 }
5450
5451 int32_t show_only_unused_tiles=4; //1 bit: hide used, 2 bit: hide unused, 4 bit: hide blank
5452 bool tile_is_used(int32_t tile)
5453 {
5454 return used_tile_table[tile];
5455 }
5456 void draw_tiles(int32_t first,int32_t cs, int32_t f)
5457 {
5458 draw_tiles(screen2, first, cs, f, true);
5459 }
5460 void draw_tiles(BITMAP* dest,int32_t first,int32_t cs, int32_t f, bool large, bool true_empty)
5461 {
5462 clear_bitmap(dest);
5463 BITMAP *buf = create_bitmap_ex(8,16,16);
5464
5465 int32_t w = 16;
5466 int32_t h = 16;
5467
5468 if(large)
5469 {
5470 w *=2;
5471 h *=2;
5472 }
5473
5474 for(int32_t i=0; i<TILES_PER_PAGE; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
5475 {
5476 int32_t x = (i%TILES_PER_ROW)<<4;
5477 int32_t y = (i/TILES_PER_ROW)<<4;
5478 int32_t l = 16;
5479
5480 if(large)
5481 {
5482 x*=2;
5483 y*=2;
5484 l*=2;
5485 }
5486
5487 l-=2;
5488
5489 if((HIDE_USED && tile_is_used(first+i) && !blank_tile_table[first+i]) // 1 bit: hide used
5490 || (HIDE_UNUSED && !tile_is_used(first+i) && !blank_tile_table[first+i]) // 2 bit: hide unused
5491 || (HIDE_BLANK && blank_tile_table[first+i])) // 4 bit: hide blank
5492 {
5493 if(!true_empty) //Use pure color 0; no effects
5494 {
5495 if (InvalidBG == 2)
5496 {
5497 draw_checkerboard(dest, x, y, w);
5498 }
5499 else if(InvalidBG == 1)
5500 {
5501 for(int32_t dy=0; dy<=l+1; dy++)
5502 {
5503 for(int32_t dx=0; dx<=l+1; dx++)
5504 {
5505 dest->line[dy+(y)][dx+(x)]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5506 }
5507 }
5508 }
5509 else
5510 {
5511 for(int32_t dy=0; dy<=l+1; dy++)
5512 {
5513 for(int32_t dx=0; dx<=l+1; dx++)
5514 {
5515 dest->line[dy+(y)][dx+(x)]=vc(0);
5516 }
5517 }
5518 rect(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5519 line(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5520 line(dest, (x)+1,(y)+l, (x)+l, (y)+1, vc(15));
5521 }
5522 }
5523 }
5524 else
5525 {
5526 puttile16(buf,first+i,0,0,cs,0);
5527 stretch_blit(buf,dest,0,0,16,16,x,y,w,h);
5528 }
5529
5530 if((f%32)<=16 && large && !HIDE_8BIT_MARKER && newtilebuf[first+i].format==tf8Bit)
5531 {
5532 textprintf_ex(dest,get_zc_font(font_z3smallfont),(x)+l-3,(y)+l-3,vc(int32_t((f%32)/6)+10),-1,"8");
5533 }
5534 }
5535
5536 destroy_bitmap(buf);
5537 }
5538
5539 void tile_info_0(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,bool rect_sel)
5540 {
5541 int32_t yofs=3;
5542 BITMAP *buf = create_bitmap_ex(8,16,16);
5543 int32_t mul = 2;
5544 FONT *tfont = get_zc_font(font_pfont);
5545
5546 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5547 _allegro_hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5548 _allegro_hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5549 tfont = get_zc_font(font_lfont_l);
5550
5551 // Copied tile and numbers
5552 jwin_draw_frame(screen2,(34*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5553 int32_t coldiff=TILECOL(copy)-TILECOL(copy+copycnt-1);
5554 if(copy>=0)
5555 {
5556 puttile16(buf,rect_sel&&coldiff>0?copy-coldiff:copy,0,0,cs,0);
5557 stretch_blit(buf,screen2,0,0,16,16,34*mul,216*mul+yofs,16*mul,16*mul);
5558
5559 if(copycnt>1)
5560 {
5561 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
5562 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
5563 }
5564 else
5565 {
5566 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
5567 }
5568 }
5569 else // No tiles copied
5570 {
5571 if (InvalidBG == 2)
5572 {
5573 draw_checkerboard(screen2, 34 * mul, 216 * mul + yofs, 16 * mul);
5574 }
5575 else if(InvalidBG == 1)
5576 {
5577 for(int32_t dy=0; dy<16*mul; dy++)
5578 {
5579 for(int32_t dx=0; dx<16*mul; dx++)
5580 {
5581 screen2->line[(216*mul+yofs+dy)][36*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5582 }
5583 }
5584 }
5585 else
5586 {
5587 rectfill(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(0));
5588 rect(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5589 line(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5590 line(screen2, 34*mul, ((216+15)*mul)+yofs, (34+15)*mul, (216*mul)+yofs, vc(15));
5591 }
5592 }
5593
5594
5595 // Current tile
5596 jwin_draw_frame(screen2,(104*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5597 puttile16(buf,tile,0,0,cs,0);
5598 stretch_blit(buf,screen2,0,0,16,16,104*mul,216*mul+yofs,16*mul,16*mul);
5599
5600 // Current selection mode
5601 jwin_draw_frame(screen2,(127*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5602 stretch_blit(select_bmp[rect_sel?1:0],screen2,0,0,16,16,127*mul,216*mul+yofs,16*mul,16*mul);
5603
5604 if(tile>tile2)
5605 {
5606 zc_swap(tile,tile2);
5607 }
5608
5609 char tbuf[8];
5610 tbuf[0]=0;
5611
5612 if(tile2!=tile)
5613 {
5614 sprintf(tbuf,"-%d",tile2);
5615 }
5616
5617 // Current tile and CSet text
5618 textprintf_ex(screen2,tfont,55*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cs: %d",cs);
5619 textprintf_right_ex(screen2,tfont,99*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile:");
5620 textprintf_right_ex(screen2,tfont,99*mul,224*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,tbuf);
5621
5622 FONT *tf = font;
5623 font = tfont;
5624
5625 draw_text_button(screen2,150*mul,213*mul+yofs,28*mul,21*mul,"&Grab",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5626 draw_text_button(screen2,(150+28)*mul,213*mul+yofs,28*mul,21*mul,"&Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5627 draw_text_button(screen2,(150+28*2)*mul,213*mul+yofs,28*mul,21*mul,"Export",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5628 draw_text_button(screen2,(150+28*3)*mul,213*mul+yofs,28*mul,21*mul,"Recolor",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5629 draw_text_button(screen2,(150+28*4)*mul,213*mul+yofs,28*mul,21*mul,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5630
5631 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5632 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5633 textprintf_centre_ex(screen2,tfont,(305*mul+4),220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5634 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5635
5636 font = tf;
5637
5638 int32_t w = 640;
5639 int32_t h = 480;
5640 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5641 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5642 int32_t screen_xofs=window_xofs+6;
5643 int32_t screen_yofs=window_yofs+25;
5644
5645 custom_vsync();
5646 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5647 SCRFIX();
5648 destroy_bitmap(buf);
5649 }
5650
5651 void tile_info_1(int32_t oldtile,int32_t oldflip,int32_t oldcs,int32_t tile,int32_t flip,int32_t cs,int32_t copy,int32_t page, bool always_use_flip)
5652 {
5653 int32_t yofs=3;
5654 BITMAP *buf = create_bitmap_ex(8,16,16);
5655 int32_t mul = 2;
5656 FONT *tfont = get_zc_font(font_pfont);
5657
5658 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5659 _allegro_hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5660 _allegro_hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5661 tfont = get_zc_font(font_lfont_l);
5662
5663 jwin_draw_frame(screen2,(124*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5664
5665 if(copy>=0)
5666 {
5667 puttile16(buf,copy,0,0,cs,flip);
5668 stretch_blit(buf,screen2,0,0,16,16,124*mul,216*mul+yofs,16*mul,16*mul);
5669 }
5670 else
5671 {
5672 if (InvalidBG == 2)
5673 {
5674 draw_checkerboard(screen2, 124 * mul, 216 * mul + yofs, 16 * mul);
5675 }
5676 else if(InvalidBG == 1)
5677 {
5678 for(int32_t dy=0; dy<16*mul; dy++)
5679 {
5680 for(int32_t dx=0; dx<16*mul; dx++)
5681 {
5682 screen2->line[216*mul+yofs+dy][124*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5683 }
5684 }
5685 }
5686 else
5687 {
5688 rectfill(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(0));
5689 rect(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5690 line(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5691 line(screen2, 124*mul, ((216+15)*mul)+yofs, (124+15)*mul, (216*mul)+yofs, vc(15));
5692 }
5693 }
5694
5695 jwin_draw_frame(screen2,(8*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5696 puttile16(buf,oldtile,0,0, oldcs, oldflip);
5697 stretch_blit(buf,screen2,0,0,16,16,8*mul,216*mul+yofs,16*mul,16*mul);
5698
5699 textprintf_right_ex(screen2,tfont,56*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Old Tile:");
5700 textprintf_ex(screen2,tfont,60*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldtile);
5701
5702 textprintf_right_ex(screen2,tfont,56*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5703 textprintf_ex(screen2,tfont,60*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldcs);
5704
5705 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5706 {
5707 textprintf_right_ex(screen2,tfont,56*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5708 textprintf_ex(screen2,tfont,60*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldflip);
5709 }
5710
5711 jwin_draw_frame(screen2,(148*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5712 puttile16(buf,tile,0,0, cs,
5713 (oldflip>0 || always_use_flip)?flip:0); // Suppress Flip for this usage
5714 stretch_blit(buf,screen2,0,0,16,16,148*mul,216*mul+yofs,16*mul,16*mul);
5715
5716 textprintf_right_ex(screen2,tfont,201*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"New Tile:");
5717 textprintf_ex(screen2,tfont,205*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",tile);
5718 textprintf_right_ex(screen2,tfont,201*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5719 textprintf_ex(screen2,tfont,205*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",cs);
5720
5721 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5722 {
5723 textprintf_right_ex(screen2,tfont,201*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5724 textprintf_ex(screen2,tfont,205*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",flip);
5725 }
5726
5727 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5728 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5729 textprintf_centre_ex(screen2,tfont,309*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5730 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5731
5732
5733 int32_t w = 640;
5734 int32_t h = 480;
5735 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5736 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5737 int32_t screen_xofs=window_xofs+6;
5738 int32_t screen_yofs=window_yofs+25;
5739
5740 custom_vsync();
5741 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5742 SCRFIX();
5743 destroy_bitmap(buf);
5744 }
5745 /*
5746 void reset_tile(tiledata *buf, int32_t t, int32_t format=1)
5747 {
5748 buf[t].format=format;
5749 if (buf[t].data!=NULL)
5750 {
5751 free(buf[t].data);
5752 }
5753 buf[t].data=(byte *)malloc(tilesize(buf[t].format));
5754 if (buf[t].data==NULL)
5755 {
5756 Z_error_fatal("Unable to initialize tile #%d.\n", t);
5757 }
5758 for(int32_t i=0; i<tilesize(buf[t].format); i++)
5759 {
5760 buf[t].data[i]=0;
5761 }
5762 }
5763 */
5764
5765 int32_t hide_used()
5766 {
5767 show_only_unused_tiles ^= 1;
5768 return D_O_K;
5769 }
5770 int32_t hide_unused()
5771 {
5772 show_only_unused_tiles ^= 2;
5773 return D_O_K;
5774 }
5775 int32_t hide_blank()
5776 {
5777 show_only_unused_tiles ^= 4;
5778 return D_O_K;
5779 }
5780 int32_t hide_8bit_marker()
5781 {
5782 show_only_unused_tiles ^= 8;
5783 return D_O_K;
5784 }
5785
5786 enum
5787 {
5788 MENUID_SELTILE_VIEW_HIDE_USED,
5789 MENUID_SELTILE_VIEW_HIDE_UNUSED,
5790 MENUID_SELTILE_VIEW_HIDE_BLANK,
5791 MENUID_SELTILE_VIEW_HIDE_8BIT,
5792 };
5793
1/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8 static NewMenu select_tile_view_menu
5794 40 {
5795
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 { "Hide Used", hide_used, MENUID_SELTILE_VIEW_HIDE_USED },
5796
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 { "Hide Unused", hide_unused, MENUID_SELTILE_VIEW_HIDE_UNUSED },
5797
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 { "Hide Blank", hide_blank, MENUID_SELTILE_VIEW_HIDE_BLANK },
5798
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 { "Hide 8-bit marker", hide_8bit_marker, MENUID_SELTILE_VIEW_HIDE_8BIT },
5799 };
5800
5801 //returns the row the tile is in on its page
5802 int32_t tile_page_row(int32_t tile)
5803 {
5804 return TILEROW(tile)-(TILEPAGE(tile)*TILE_ROWS_PER_PAGE);
5805 }
5806
5807 enum {ti_none, ti_encompass, ti_broken};
5808
5809 //striped check and striped selection
5810 int32_t move_intersection_ss(newcombo &cmb, int32_t selection_first, int32_t selection_last, int32_t offset = 0)
5811 {
5812 int32_t cmb_first = cmb.o_tile;
5813 int32_t cmb_last = cmb.o_tile;
5814 do
5815 {
5816 cmb_last = cmb.tile;
5817 animate(cmb, true);
5818 }
5819 while(cmb.tile != cmb.o_tile);
5820 reset_combo_animation(cmb);
5821 cmb_first += offset;
5822 cmb_last += offset;
5823
5824 if(cmb_first > selection_last || cmb_last < selection_first)
5825 return ti_none;
5826 if(cmb_first >= selection_first && cmb_last <= selection_last)
5827 return ti_encompass;
5828
5829 do
5830 {
5831 if(cmb.tile+offset >= selection_first && cmb.tile+offset <= selection_last)
5832 {
5833 reset_combo_animation(cmb);
5834 return ti_broken; //contained, but non-encompassing.
5835 }
5836 animate(cmb, true);
5837 }
5838 while(cmb.tile != cmb.o_tile);
5839 reset_combo_animation(cmb);
5840 return ti_none;
5841 }
5842 int32_t move_intersection_ss(int32_t check_first, int32_t check_last, int32_t selection_first, int32_t selection_last)
5843 {
5844 // if selection is before or after check...
5845 if((check_first>selection_last)||(selection_first>check_last))
5846 {
5847 return ti_none;
5848 }
5849
5850 // if selection envelopes check
5851 if((selection_first<=check_first)&&(selection_last>=check_last))
5852 {
5853 return ti_encompass; //encompass
5854 }
5855
5856 //everything else is a break
5857 return ti_broken; //intersect
5858 }
5859
5860
5861
5862 //rectangular check and striped selection
5863 int32_t move_intersection_rs(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_first, int32_t selection_last)
5864 {
5865 int32_t ret1=-1, ret2=-1;
5866
5867 for(int32_t i=0; i<check_height; ++i)
5868 {
5869 int32_t check_first=((check_top+i)*TILES_PER_ROW)+check_left;
5870 int32_t check_last=check_first+check_width-1;
5871 ret2=move_intersection_ss(check_first, check_last, selection_first, selection_last);
5872
5873 if(ret2==ti_broken)
5874 {
5875 return ti_broken;
5876 }
5877
5878 ret1=(ret2==ti_encompass?ti_encompass:ret1);
5879 }
5880
5881 if(ret1==ti_encompass)
5882 {
5883 if((TILEROW(selection_first)<=check_top) &&
5884 (TILEROW(selection_last)>=(check_top+check_height-1)))
5885 {
5886 return ti_encompass;
5887 }
5888 else
5889 {
5890 return ti_broken;
5891 }
5892 }
5893
5894 return ti_none;
5895 }
5896
5897
5898 //striped check and rectangular selection
5899 int32_t move_intersection_sr(newcombo &cmb, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height, int32_t offset = 0)
5900 {
5901 if(selection_width < TILES_PER_ROW)
5902 {
5903 int32_t cmb_first = cmb.o_tile;
5904 int32_t cmb_last = cmb.o_tile;
5905 do
5906 {
5907 cmb_last = cmb.tile;
5908 animate(cmb, true);
5909 }
5910 while(cmb.tile != cmb.o_tile);
5911 reset_combo_animation(cmb);
5912 cmb_first += offset;
5913 cmb_last += offset;
5914
5915 if((TILEROW(cmb_first)>=selection_top) &&
5916 (TILEROW(cmb_last)<=selection_top+selection_height-1) &&
5917 (TILECOL(cmb_first)>=selection_left) &&
5918 (TILECOL(cmb_last)<=TILECOL(selection_left+selection_width-1)))
5919 {
5920 return ti_encompass;
5921 }
5922 else if((cmb_last<selection_top*TILES_PER_ROW+selection_left) ||
5923 (cmb_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
5924 {
5925 return ti_none;
5926 }
5927
5928 if(TILEROW(cmb_first) == TILEROW(cmb_last))
5929 {
5930 int32_t firstcol = TILECOL(cmb_first);
5931 int32_t lastcol = TILECOL(cmb_last);
5932
5933 if(lastcol < selection_left || firstcol >= selection_left+selection_width)
5934 return ti_none;
5935 else //handle skip x
5936 {
5937 do
5938 {
5939 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width)
5940 {
5941 reset_combo_animation(cmb);
5942 return ti_broken;
5943 }
5944 animate(cmb, true);
5945 }
5946 while(cmb.tile != cmb.o_tile);
5947 reset_combo_animation(cmb);
5948 return ti_none;
5949 }
5950 }
5951 else //multi-row combo...
5952 {
5953 int32_t row = TILEROW(cmb_first);
5954
5955 do
5956 {
5957 if(row < selection_top || row > selection_top+selection_height-1)
5958 {
5959 //This row isn't in the selection; skip to next row
5960 do
5961 {
5962 animate(cmb,true);
5963 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5964 }
5965 while(TILEROW(cmb.tile) == row);
5966 row = TILEROW(cmb.tile);
5967 continue;
5968 }
5969
5970 //This row IS in the selection; check each tile.
5971 do
5972 {
5973 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width-1)
5974 {
5975 reset_combo_animation(cmb);
5976 return ti_broken;
5977 }
5978 animate(cmb, true);
5979 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5980 }
5981 while(TILEROW(cmb.tile) == row);
5982 row = TILEROW(cmb.tile);
5983 }
5984 while(cmb.tile != cmb.o_tile);
5985
5986 return ti_none; //...Theoretically unreachable, but if it DOES get here, it's done.
5987 }
5988 }
5989
5990 return move_intersection_ss(cmb, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1, offset);
5991 }
5992 int32_t move_intersection_sr(int32_t check_first, int32_t check_last, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
5993 {
5994 if(selection_width < TILES_PER_ROW)
5995 {
5996 if((check_last-check_first+1<=selection_width) &&
5997 (TILEROW(check_first)>=selection_top) &&
5998 (TILEROW(check_last)<=selection_top+selection_height-1) &&
5999 (TILECOL(check_first)>=selection_left) &&
6000 (TILECOL(check_last)<=TILECOL(selection_left+selection_width-1)))
6001 {
6002 return ti_encompass;
6003 }
6004 else if((check_last<selection_top*TILES_PER_ROW+selection_left) ||
6005 (check_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
6006 {
6007 return ti_none;
6008 }
6009
6010 //else if (selection_top*TILES_PER_ROW+selection_left<check_first && (selection_top+1)*TILES_PER_ROW+selection_left>check_last)
6011
6012 //one last base case: the strip we're interested in only lies along one row
6013 if(check_first/TILES_PER_ROW == check_last/TILES_PER_ROW)
6014 {
6015 int32_t cfcol = check_first%TILES_PER_ROW;
6016 int32_t clcol = check_last%TILES_PER_ROW;
6017
6018 if(clcol < selection_left || cfcol >= selection_left+selection_width)
6019 return ti_none;
6020 else
6021 return ti_broken;
6022 }
6023 else
6024 {
6025 //recursively cut the strip into substrips which lie entirely on one row
6026 int32_t currow = check_first/TILES_PER_ROW;
6027 int32_t endrow = check_last/TILES_PER_ROW;
6028 int32_t accum = 0;
6029 accum |= move_intersection_sr(check_first,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6030
6031 for(++currow; currow<endrow; currow++)
6032 {
6033 accum |= move_intersection_sr(currow*TILES_PER_ROW,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6034 }
6035
6036 accum |= move_intersection_sr(currow*TILES_PER_ROW, check_last,selection_left,selection_top,selection_width,selection_height);
6037
6038 if(accum > 0)
6039 return ti_broken;
6040
6041 return ti_none;
6042 }
6043 }
6044
6045 return move_intersection_ss(check_first, check_last, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1);
6046 }
6047
6048 //rectangular check and rectangular selection
6049 int32_t move_intersection_rr(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6050 {
6051 if((check_left>=selection_left) &&
6052 (check_left+check_width<=selection_left+selection_width) &&
6053 (check_top>=selection_top) &&
6054 (check_top+check_height<=selection_top+selection_height))
6055 {
6056 return ti_encompass;
6057 }
6058 else
6059 {
6060 for(int32_t i=check_top; i<check_top+check_height; ++i)
6061 {
6062 if(move_intersection_rs(selection_left, selection_top, selection_width, selection_height, i*TILES_PER_ROW+check_left, i*TILES_PER_ROW+check_left+check_width-1)!=ti_none)
6063 {
6064 return ti_broken;
6065 }
6066 }
6067 }
6068
6069 return ti_none;
6070 }
6071
6072
6073
6074
6075 static DIALOG move_textbox_list_dlg[] =
6076 {
6077 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
6078 8 { jwin_win_proc, 0, 0, 300, 212, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6079 8 { jwin_ctext_proc, 150, 18, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6080 8 { jwin_ctext_proc, 150, 28, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6081 8 { jwin_textbox_proc, 12, 40, 277, 138, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6082 8 { jwin_button_proc, 80, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
6083 8 { jwin_button_proc, 160, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
6084 8 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
6085 8 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
6086 };
6087
6088 bool popup_move_textbox_dlg(string const& msg, char* textbox, char const* title)
6089 {
6090 char buf1[512] = {0};
6091 char buf2[512] = {0};
6092 large_dialog(move_textbox_list_dlg);
6093 DIALOG& tbox = move_textbox_list_dlg[3];
6094 {
6095 FONT* f = tbox.dp2 ? (FONT*)tbox.dp2 : get_custom_font(CFONT_GUI);
6096 int indx = 0, word_indx = 0;
6097 for(char c : msg)
6098 {
6099 if(c == ' ' || c == '\n')
6100 word_indx = indx;
6101 buf1[indx++] = c;
6102 if(c == '\n' || text_length(f, buf1) >= tbox.w)
6103 {
6104 buf1[word_indx] = 0;
6105 strcpy(buf2, msg.c_str()+word_indx+1);
6106 break;
6107 }
6108 }
6109 }
6110
6111 move_textbox_list_dlg[0].dp = (void*)title;
6112 move_textbox_list_dlg[0].dp2 = get_zc_font(font_lfont);
6113 move_textbox_list_dlg[1].dp = buf1;
6114 move_textbox_list_dlg[2].dp = buf2;
6115 tbox.dp = textbox;
6116 tbox.d2 = 0;
6117 auto tby = tbox.y;
6118 auto tbh = tbox.h;
6119 if(!buf2[0])
6120 {
6121 auto diff = move_textbox_list_dlg[2].h;
6122 tbox.y -= diff;
6123 tbox.h += diff;
6124 }
6125
6126 int32_t ret=do_zqdialog(move_textbox_list_dlg,2);
6127 position_mouse_z(0);
6128 tbox.y = tby;
6129 tbox.h = tbh;
6130
6131 return ret == 4;
6132 }
6133
6134 int32_t quick_select_3(int32_t a, int32_t b, int32_t c, int32_t d)
6135 {
6136 return a==0?b:a==1?c:d;
6137 }
6138
6139 bool TileMoveList::process(std::unique_ptr<BaseTileRef>& ref, TileMoveProcess const& proc, bool is_dest)
6140 {
6141 TileRefCombo* combo_ref = dynamic_cast<TileRefCombo*>(ref.get());
6142 int i = ti_none;
6143 auto t = ref->getTile() + ref->offset();
6144
6145 if(combo_ref)
6146 {
6147 if(proc.rect)
6148 i=move_intersection_sr(*combo_ref->combo, proc._l, proc._t, proc._w, proc._h);
6149 else i=move_intersection_ss(*combo_ref->combo, proc._first, proc._last);
6150 }
6151 else if(proc.rect)
6152 {
6153 if(ref->h > 1)
6154 i=move_intersection_rr(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._l, proc._t, proc._w, proc._h);
6155 else i=move_intersection_sr(t, t+ref->w-1, proc._l, proc._t, proc._w, proc._h);
6156 }
6157 else
6158 {
6159 if(ref->h > 1)
6160 i=move_intersection_rs(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._first, proc._last);
6161 else i=move_intersection_ss(t, t+ref->w-1, proc._first, proc._last);
6162 }
6163
6164 bool in = i != ti_none, out = i != ti_encompass;
6165 for(size_t q = 0; !(in&&out) && q < ref->extra_rects.size(); ++q)
6166 {
6167 auto [ex_t,ex_w,ex_h] = ref->extra_rects[q];
6168 if(proc.rect)
6169 i = move_intersection_rr(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._l, proc._t, proc._w, proc._h);
6170 else i = move_intersection_rs(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._first, proc._last);
6171 if(i != ti_none)
6172 in = true;
6173 if(i != ti_encompass)
6174 out = true;
6175 }
6176 i = in ? (out ? ti_broken : ti_encompass) : ti_none;
6177
6178 if(i != ti_none && ref->getTile() != 0)
6179 {
6180 if(mode == Mode::CHECK_ALL)
6181 {
6182 move_refs.emplace_back(std::move(ref));
6183 return true;
6184 }
6185 else if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6186 {
6187 if(warning_flood || warning_list.tellp() >= 65000)
6188 {
6189 if(!warning_flood)
6190 warning_list << "...\n...\n...\nmany others";
6191 warning_flood = true;
6192 }
6193 else
6194 warning_list << ref->name << '\n';
6195 }
6196 else if(i==ti_encompass)
6197 {
6198 move_refs.emplace_back(std::move(ref));
6199 return true;
6200 }
6201 }
6202 return false;
6203 }
6204
6205 bool TileMoveList::check_prot()
6206 {
6207 if(!TileProtection)
6208 return true;
6209 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Tile Warning");
6210
6211 warning_flood = false;
6212 warning_list.clear();
6213
6214 return ret;
6215 }
6216
6217 void TileMoveList::add_diff(int diff)
6218 {
6219 for(auto& ref : move_refs)
6220 ref->addTile(diff);
6221 }
6222
6223 //from 'combo.h'
6224 bool ComboMoveList::process(std::unique_ptr<BaseComboRef>& ref, ComboMoveProcess const& proc, bool is_dest)
6225 {
6226 int i = ti_none;
6227 auto c = ref->getCombo();
6228
6229 if(ref->no_move)
6230 processed_combos[c] = true;
6231 else processed_combos[c]; //inserts element if does not exist
6232 i = move_intersection_ss(c, c, proc._first, proc._last);
6233
6234 if(i != ti_none && ref->getCombo() != 0)
6235 {
6236 if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6237 {
6238 if(ComboProtection)
6239 {
6240 if(warning_flood || warning_list.tellp() >= 65000)
6241 {
6242 if(!warning_flood)
6243 warning_list << "...\n...\n...\nmany others";
6244 warning_flood = true;
6245 }
6246 else
6247 warning_list << ref->name << '\n';
6248 }
6249 }
6250 else if(i==ti_encompass)
6251 {
6252 move_refs.emplace_back(std::move(ref));
6253 return true;
6254 }
6255 }
6256 return false;
6257 }
6258
6259 bool ComboMoveList::check_prot()
6260 {
6261 if(!ComboProtection)
6262 return true;
6263 vector<set<int> const*> subset = combo_links.subset(processed_combos);
6264 bool subset_header = false;
6265 for(int q = 0; q < 2; ++q)
6266 {
6267 bool is_dest = (q==1);
6268 if(!is_dest && !source_process)
6269 continue;
6270 ComboMoveProcess const& proc = is_dest ? dest_process : *source_process;
6271 for(auto it = subset.begin(); it != subset.end();)
6272 {
6273 auto s = *it;
6274 if(warning_flood || warning_list.tellp() >= 65000)
6275 {
6276 if(!warning_flood)
6277 warning_list << "...\n...\n...\nmany others";
6278 warning_flood = true;
6279 break;
6280 }
6281 set<int> in_set, out_set;
6282 bool no_move = is_dest;
6283 for(int c : *s)
6284 {
6285 int i = move_intersection_ss(c, c, proc._first, proc._last);
6286 if(i != ti_none)
6287 in_set.insert(c);
6288 if(i != ti_encompass)
6289 out_set.insert(c);
6290 if(!no_move)
6291 {
6292 auto it = processed_combos.find(c);
6293 if(it != processed_combos.end() && it->second)
6294 no_move = true;
6295 }
6296 }
6297 int i = in_set.empty() ? ti_none : (out_set.empty() ? ti_encompass : ti_broken);
6298 if(i == ti_encompass && !no_move)
6299 {
6300 it = subset.erase(it);
6301 continue;
6302 }
6303 if(i == ti_none)
6304 {
6305 ++it;
6306 continue;
6307 }
6308
6309 if(!subset_header)
6310 {
6311 subset_header = true;
6312 warning_list << "===== Broken Relative Combo Groups =====\n";
6313 }
6314 bool comma = false;
6315 warning_list << "In(";
6316 for(int c : in_set)
6317 {
6318 if(comma)
6319 warning_list << ",";
6320 else comma = true;
6321 warning_list << c;
6322 }
6323 warning_list << "),Out(";
6324 comma = false;
6325 for(int c : out_set)
6326 {
6327 if(comma)
6328 warning_list << ",";
6329 else comma = true;
6330 warning_list << c;
6331 }
6332 warning_list << ")\n";
6333 it = subset.erase(it);
6334 }
6335 }
6336 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Combo Warning");
6337
6338 processed_combos.clear();
6339 warning_flood = false;
6340 warning_list.clear();
6341
6342 return ret;
6343 }
6344
6345 void ComboMoveList::add_diff(int diff)
6346 {
6347 for(auto& ref : move_refs)
6348 ref->addCombo(diff);
6349 }
6350
6351 bool _handle_tile_move(TileMoveProcess dest_process, optional<TileMoveProcess> source_process, int diff, TileMoveUndo* on_undo = nullptr, std::function<void(int32_t)> every_proc = nullptr, TileMoveList::Mode mode = TileMoveList::Mode::MOVE)
6352 {
6353 bool BSZ2 = get_qr(qr_BSZELDA);
6354 bool move = source_process.has_value();
6355 TileMoveUndo local_undo;
6356 TileMoveUndo& storage = on_undo ? *on_undo : local_undo;
6357 auto& vec = storage.vec;
6358 storage.diff = diff;
6359 storage.state = false;
6360
6361 //Combos
6362 {
6363 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6364 dest_process, source_process, mode,
6365 move
6366 ? "The tiles used by the following combos will be partially cleared by the move."
6367 : "The tiles used by the following combos will be partially or completely overwritten by this process."
6368 ));
6369 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6370 {
6371 auto& cmb = combobuf[q];
6372 auto lbl = fmt::format("Combo {}{}", q, cmb.label.empty() ? ""
6373 : fmt::format(" ({})", cmb.label));
6374 movelist->add_combo(&cmb, lbl);
6375
6376 //type-specific
6377 char const* type_name = ZI.getComboTypeName(cmb.type);
6378 switch(cmb.type)
6379 {
6380 case cSPOTLIGHT:
6381 {
6382 if(!(cmb.usrflags & cflag1))
6383 break;
6384 movelist->add_tile_10k(&cmb.attributes[0], 16, 1, fmt::format("{} - Type '{}' - Beam Tiles", lbl, type_name));
6385 break;
6386 }
6387 }
6388 }
6389 if(!every_proc && !movelist->check_prot())
6390 return false;
6391 }
6392 //Items
6393 {
6394 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6395 dest_process, source_process, mode,
6396 move
6397 ? "The tiles used by the following items will be partially cleared by the move."
6398 : "The tiles used by the following items will be partially or completely overwritten by this process."
6399 ));
6400 build_bii_list(false);
6401 for(int32_t u=0; u<MAXITEMS; u++)
6402 {
6403 auto id = bii[u].i;
6404 itemdata& itm = itemsbuf[id];
6405 if(itm.family == itype_bottle)
6406 {
6407 vector<std::tuple<int,int,int>> rects;
6408 auto fr = itm.frames;
6409 for(int q = 0; q < NUM_BOTTLE_TYPES; ++q)
6410 {
6411 bottletype const& bt = QMisc.bottle_types[q];
6412 if(bt.is_blank())
6413 continue;
6414 rects.emplace_back(fr+q*fr, fr, 1);
6415 }
6416 movelist->add_tile(&itm.tile, fr, 1, fmt::format("Item {}", id),
6417 false, 0, 0, rects);
6418 }
6419 else movelist->add_tile(&itm.tile, itm.frames, 1, fmt::format("Item {}", id));
6420 }
6421 if(!every_proc && !movelist->check_prot())
6422 return false;
6423 }
6424 //Weapon sprites
6425 {
6426 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6427 dest_process, source_process, mode,
6428 move
6429 ? "The tiles used by the following weapons will be partially cleared by the move."
6430 : "The tiles used by the following weapons will be partially or completely overwritten by this process."
6431 ));
6432 build_biw_list();
6433
6434 for(int32_t u=0; u<MAXWPNS; u++)
6435 {
6436 bool ignore_frames=false;
6437 int32_t m=0;
6438
6439 auto id = biw[u].i;
6440 auto& wpn = wpnsbuf[id];
6441
6442 switch(biw[u].i)
6443 {
6444 case wSWORD:
6445 case wWSWORD:
6446 case wMSWORD:
6447 case wXSWORD:
6448 m=3+((wpnsbuf[biw[u].i].type==3)?1:0);
6449 break;
6450
6451 case wSWORDSLASH:
6452 case wWSWORDSLASH:
6453 case wMSWORDSLASH:
6454 case wXSWORDSLASH:
6455 m=4;
6456 break;
6457
6458 case iwMMeter:
6459 m=9;
6460 break;
6461
6462 case wBRANG:
6463 case wMBRANG:
6464 case wFBRANG:
6465 m=BSZ2?1:3;
6466 break;
6467
6468 case wBOOM:
6469 case wSBOOM:
6470 case ewBOOM:
6471 case ewSBOOM:
6472 ignore_frames=true;
6473 m=2;
6474 break;
6475
6476 case wWAND:
6477 m=1;
6478 break;
6479
6480 case wMAGIC:
6481 m=1;
6482 break;
6483
6484 case wARROW:
6485 case wSARROW:
6486 case wGARROW:
6487 case ewARROW:
6488 m=1;
6489 break;
6490
6491 case wHAMMER:
6492 m=8;
6493 break;
6494
6495 case wHSHEAD:
6496 m=1;
6497 break;
6498
6499 case wHSCHAIN_H:
6500 m=1;
6501 break;
6502
6503 case wHSCHAIN_V:
6504 m=1;
6505 break;
6506
6507 case wHSHANDLE:
6508 m=1;
6509 break;
6510
6511 case iwDeath:
6512 m=BSZ2?4:2;
6513 break;
6514
6515 case iwSpawn:
6516 m=3;
6517 break;
6518
6519 default:
6520 m=0;
6521 break;
6522 }
6523
6524 movelist->add_tile(&wpn.tile, zc_max((ignore_frames?0:wpn.frames),1)+m,
6525 1, fmt::format("{} {}", biw[u].s, id));
6526
6527 //Tile 54+55 are "Impact (not shown in sprite list)", for u==3 "Arrow" and u==9 "Boomerang"
6528 //...these can't be updated by a move.
6529 if((u==3)||(u==9))
6530 {
6531 static int32_t impact_tiles[2] = {54,54};
6532 auto& tile = impact_tiles[u==3 ? 0 : 1];
6533 tile = 54; //dummy tile, ensure it's correct
6534 movelist->add_tile(&tile, 2, 1,
6535 fmt::format("{} Impact (not shown in sprite list)",(u==3)?"Arrow":"Boomerang"),
6536 true);
6537 }
6538 }
6539 if(!every_proc && !movelist->check_prot())
6540 return false;
6541 }
6542 //Player sprites
6543 {
6544 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6545 dest_process, source_process, mode,
6546 move
6547 ? "The tiles used by the following player sprites will be partially cleared by the move."
6548 : "The tiles used by the following player sprites will be partially or completely overwritten by this process."
6549 ));
6550 {
6551 int32_t a_style=(zinit.heroAnimationStyle);
6552 #define ADD_PLAYER_SPRITE(ref_sprite, frames, name) \
6553 do \
6554 { \
6555 movelist->add_tile(&ref_sprite[spr_tile], \
6556 (ref_sprite[spr_extend] < 2 ? 1 : 2) * frames, \
6557 ref_sprite[spr_extend] < 1 ? 1 : 2, \
6558 name, false, \
6559 ref_sprite[spr_extend] < 2 ? 0 : -1, \
6560 ref_sprite[spr_extend] < 1 ? 0 : -1); \
6561 } while(false)
6562 // + (ref_sprite[spr_extend] < 2 ? 0 : 1) //this was on some of the 'width's before... but doesn't make sense?
6563
6564 for(int32_t i=0; i<4; ++i)
6565 {
6566 ADD_PLAYER_SPRITE(walkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Walking ({})", dirstr_proper[i]));
6567 }
6568
6569 for(int32_t i=0; i<4; ++i)
6570 {
6571 ADD_PLAYER_SPRITE(slashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slashing ({})", dirstr_proper[i]));
6572 }
6573
6574 for(int32_t i=0; i<4; ++i)
6575 {
6576 ADD_PLAYER_SPRITE(stabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Stabbing ({})", dirstr_proper[i]));
6577 }
6578
6579 for(int32_t i=0; i<4; ++i)
6580 {
6581 ADD_PLAYER_SPRITE(poundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Pounding ({})", dirstr_proper[i]));
6582 }
6583
6584 for(int32_t i=0; i<2; ++i)
6585 {
6586 ADD_PLAYER_SPRITE(holdspr[0][i], 1, fmt::format("Hold (Land, {}-hand)", i+1));
6587 }
6588
6589 ADD_PLAYER_SPRITE(castingspr, 1, "Casting");
6590
6591 for(int32_t i=0; i<4; ++i)
6592 {
6593 ADD_PLAYER_SPRITE(floatspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Floating ({})", dirstr_proper[i]));
6594 }
6595
6596 for(int32_t i=0; i<4; ++i)
6597 {
6598 ADD_PLAYER_SPRITE(swimspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Swimming ({})", dirstr_proper[i]));
6599 }
6600
6601 for(int32_t i=0; i<4; ++i)
6602 {
6603 ADD_PLAYER_SPRITE(divespr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Diving ({})", dirstr_proper[i]));
6604 }
6605
6606 for(int32_t i=0; i<2; ++i)
6607 {
6608 ADD_PLAYER_SPRITE(holdspr[1][i], 1, fmt::format("Hold (Water, {}-hand)", i));
6609 }
6610
6611 for(int32_t i=0; i<4; ++i)
6612 {
6613 ADD_PLAYER_SPRITE(jumpspr[i], 3, fmt::format("Jumping ({})", dirstr_proper[i]));
6614 }
6615
6616 for(int32_t i=0; i<4; ++i)
6617 {
6618 ADD_PLAYER_SPRITE(chargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Charging ({})", dirstr_proper[i]));
6619 }
6620 for(int32_t i=0; i<4; ++i)
6621 {
6622 ADD_PLAYER_SPRITE(revslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slash 2 ({})", dirstr_proper[i]));
6623 }
6624 for(int32_t i=0; i<4; ++i)
6625 {
6626 ADD_PLAYER_SPRITE(fallingspr[i], 7, fmt::format("Falling ({})", dirstr_proper[i]));
6627 }
6628 for(int32_t i=0; i<4; ++i)
6629 {
6630 ADD_PLAYER_SPRITE(liftingspr[i], liftingspr[i][spr_frames], fmt::format("Lifting ({})", dirstr_proper[i]));
6631 }
6632 for(int32_t i=0; i<4; ++i)
6633 {
6634 ADD_PLAYER_SPRITE(liftingwalkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Lift-Walking ({})", dirstr_proper[i]));
6635 }
6636 for(int32_t i=0; i<4; ++i)
6637 {
6638 ADD_PLAYER_SPRITE(drowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Drowning ({})", dirstr_proper[i]));
6639 }
6640 for(int32_t i=0; i<4; ++i)
6641 {
6642 ADD_PLAYER_SPRITE(drowning_lavaspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Lava Drowning ({})", dirstr_proper[i]));
6643 }
6644 for(int32_t i=0; i<4; ++i)
6645 {
6646 ADD_PLAYER_SPRITE(sideswimspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swimming ({})", dirstr_proper[i]));
6647 }
6648 //69
6649 for(int32_t i=0; i<4; ++i)
6650 {
6651 ADD_PLAYER_SPRITE(sideswimslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Side-Swim Slash ({})", dirstr_proper[i]));
6652 }
6653 //73
6654 for(int32_t i=0; i<4; ++i)
6655 {
6656 ADD_PLAYER_SPRITE(sideswimstabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Stab ({})", dirstr_proper[i]));
6657 }
6658 //77
6659 for(int32_t i=0; i<4; ++i)
6660 {
6661 ADD_PLAYER_SPRITE(sideswimpoundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Pound ({})", dirstr_proper[i]));
6662 }
6663 //81
6664 for(int32_t i=0; i<4; ++i)
6665 {
6666 ADD_PLAYER_SPRITE(sideswimchargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Side-Swim Charging ({})", dirstr_proper[i]));
6667 }
6668 //85
6669 ADD_PLAYER_SPRITE(sideswimholdspr[spr_hold1], 1, "Hold (Side-Water, 1-hand)");
6670 ADD_PLAYER_SPRITE(sideswimholdspr[spr_hold2], 1, "Hold (Side-Water, 2-hand)");
6671 ADD_PLAYER_SPRITE(sideswimcastingspr, 1, "Side-Swim Casting");
6672 for(int32_t i=0; i<4; ++i)
6673 {
6674 ADD_PLAYER_SPRITE(sidedrowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swim Drowning ({})", dirstr_proper[i]));
6675 }
6676 //91
6677 }
6678 if(!every_proc && !movelist->check_prot())
6679 return false;
6680 }
6681 //Map Styles
6682 {
6683 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6684 dest_process, source_process, mode,
6685 move
6686 ? "The tiles used by the following map styles will be partially cleared by the move."
6687 : "The tiles used by the following map styles will be partially or completely overwritten by this process."
6688 ));
6689 movelist->add_tile(&QMisc.colors.blueframe_tile, 2, 2, "Frame");
6690 movelist->add_tile(&QMisc.colors.HCpieces_tile, zinit.hcp_per_hc, 1, "Heart Container Piece");
6691 movelist->add_tile(&QMisc.colors.triforce_tile, BSZ2?2:1, BSZ2?3:1, "McGuffin Fragment");
6692 movelist->add_tile(&QMisc.colors.triframe_tile, BSZ2?7:6, BSZ2?7:3, "McGuffin Frame");
6693 movelist->add_tile(&QMisc.colors.overworld_map_tile, 5, 3, "Overworld Map");
6694 movelist->add_tile(&QMisc.colors.dungeon_map_tile, 5, 3, "Dungeon Map");
6695 if(!every_proc && !movelist->check_prot())
6696 return false;
6697 }
6698 //Game Icons
6699 {
6700 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6701 dest_process, source_process, mode,
6702 move
6703 ? "The tiles used by the following game icons will be partially cleared by the move."
6704 : "The tiles used by the following game icons will be partially or completely overwritten by this process."
6705 ));
6706 for(int32_t u=0; u<4; u++)
6707 movelist->add_tile(&QMisc.icons[u], fmt::format("Game Icon {}", u));
6708 if(!every_proc && !movelist->check_prot())
6709 return false;
6710 }
6711 //DMaps
6712 {
6713 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6714 dest_process, source_process, mode,
6715 move
6716 ? "The tiles used by the following dmaps will be partially cleared by the move."
6717 : "The tiles used by the following dmaps will be partially or completely overwritten by this process."
6718 ));
6719 for(int32_t u=0; u<MAXDMAPS; u++)
6720 {
6721 auto& dm = DMaps[u];
6722 movelist->add_tile(&dm.minimap_1_tile, 5, 3, fmt::format("DMap {} - Minimap (Empty)", u));
6723 movelist->add_tile(&dm.minimap_2_tile, 5, 3, fmt::format("DMap {} - Minimap (Filled)", u));
6724 movelist->add_tile(&dm.largemap_1_tile, BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Empty)", u));
6725 movelist->add_tile(&dm.largemap_2_tile, BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Filled)", u));
6726 }
6727 if(!every_proc && !movelist->check_prot())
6728 return false;
6729 }
6730 //Enemies
6731 {
6732 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6733 dest_process, source_process, mode,
6734 move
6735 ? "The tiles used by the following enemies will be partially cleared by the move."
6736 : "The tiles used by the following enemies will be partially or completely overwritten by this process."
6737 ));
6738 build_bie_list(false);
6739 bool newtiles=get_qr(qr_NEWENEMYTILES)!=0;
6740 for(int u=0; u<eMAXGUYS; u++)
6741 {
6742 guydata& enemy=guysbuf[bie[u].i];
6743 bool darknut=false;
6744 int32_t gleeok=0;
6745
6746 if(enemy.family==eeWALK && ((enemy.flags&(inv_back|inv_front|inv_left|inv_right))!=0))
6747 darknut=true;
6748 else if(enemy.family==eeGLEEOK)
6749 {
6750 // Not certain this is the right thing to check...
6751 if(enemy.misc3==0)
6752 gleeok=1;
6753 else
6754 gleeok=2;
6755 }
6756
6757 // Dummied out enemies
6758 if(bie[u].i>=eOCTO1S && bie[u].i<e177)
6759 {
6760 if(old_guy_string[bie[u].i][strlen(old_guy_string[bie[u].i])-1]==' ')
6761 {
6762 continue;
6763 }
6764 }
6765
6766 if(newtiles)
6767 {
6768 if(guysbuf[bie[u].i].e_tile==0)
6769 {
6770 continue;
6771 }
6772
6773 vector<std::tuple<int,int,int>> rects;
6774
6775 if(darknut)
6776 {
6777 rects.emplace_back(enemy.e_tile+6*TILES_PER_ROW, enemy.e_width, enemy.e_height);
6778 }
6779 else if(enemy.family==eeGANON)
6780 {
6781 rects.emplace_back(enemy.e_tile+2*TILES_PER_ROW, 20, 4);
6782 }
6783 else if(gleeok) //No idea if this is actually *RIGHT*, but I copied what was here before faithfully -Em
6784 {
6785 for(int32_t j=0; j<4; ++j)
6786 {
6787 rects.emplace_back(
6788 TILECOL(guysbuf[bie[u].i].e_tile+(gleeok>1?-4:8)) + TILES_PER_ROW*TILEROW(guysbuf[bie[u].i].e_tile+8)+(j<<1)+(gleeok>1?1:0),
6789 4, 1);
6790 }
6791 int32_t c=TILECOL(guysbuf[bie[u].i].e_tile)+(gleeok>1?-12:0);
6792 int32_t r=TILEROW(guysbuf[bie[u].i].e_tile)+(gleeok>1?17:8);
6793 rects.emplace_back(c+TILES_PER_ROW*r, 20, 3);
6794 rects.emplace_back(c+TILES_PER_ROW*(r+3), 16, 6);
6795 }
6796 movelist->add_tile(&enemy.e_tile, enemy.e_width, enemy.e_height, fmt::format("Enemy {} ({}) 'New'", u, bie[u].s),
6797 false, 0, 0, rects);
6798 }
6799 else
6800 {
6801 if(guysbuf[bie[u].i].tile==0)
6802 {
6803 continue;
6804 }
6805 movelist->add_tile(&enemy.tile, enemy.width, enemy.height, fmt::format("Enemy {} ({}) 'Old'", u, bie[u].s));
6806
6807 if(guysbuf[bie[u].i].s_tile!=0)
6808 {
6809 movelist->add_tile(&enemy.s_tile, enemy.s_width, enemy.s_height, fmt::format("Enemy {} ({}) 'Special'", u, bie[u].s));
6810 }
6811 }
6812 }
6813 if(!every_proc && !movelist->check_prot())
6814 return false;
6815 }
6816 //Subscreens
6817 {
6818 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6819 dest_process, source_process, mode,
6820 move
6821 ? "The tiles used by the following subscreen widgets will be partially cleared by the move."
6822 : "The tiles used by the following subscreen widgets will be partially or completely overwritten by this process."
6823 ));
6824
6825 for(auto q = 0; q < subscreens_active.size(); ++q)
6826 {
6827 size_t indx = movelist->move_refs.size();
6828 subscreens_active[q].collect_tiles(*movelist.get());
6829 for(; indx < movelist->move_refs.size(); ++indx)
6830 {
6831 auto& ref = movelist->move_refs[indx];
6832 ref->name = fmt::format("Active Subscr {} - {}", q, ref->name);
6833 }
6834 }
6835 for(auto q = 0; q < subscreens_passive.size(); ++q)
6836 {
6837 size_t indx = movelist->move_refs.size();
6838 subscreens_passive[q].collect_tiles(*movelist.get());
6839 for(; indx < movelist->move_refs.size(); ++indx)
6840 {
6841 auto& ref = movelist->move_refs[indx];
6842 ref->name = fmt::format("Passive Subscr {} - {}", q, ref->name);
6843 }
6844 }
6845 for(auto q = 0; q < subscreens_overlay.size(); ++q)
6846 {
6847 size_t indx = movelist->move_refs.size();
6848 subscreens_overlay[q].collect_tiles(*movelist.get());
6849 for(; indx < movelist->move_refs.size(); ++indx)
6850 {
6851 auto& ref = movelist->move_refs[indx];
6852 ref->name = fmt::format("Overlay Subscr {} - {}", q, ref->name);
6853 }
6854 }
6855 if(!every_proc && !movelist->check_prot())
6856 return false;
6857 }
6858 //Strings
6859 {
6860 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6861 dest_process, source_process, mode,
6862 move
6863 ? "The tiles used by the following strings will be partially cleared by the move."
6864 : "The tiles used by the following strings will be partially or completely overwritten by this process."
6865 ));
6866 for(size_t q = 0; q < msg_count; ++q)
6867 {
6868 MsgStr& str = MsgStrings[q];
6869 bool fulltile = str.stringflags & STRINGFLAG_FULLTILE;
6870 movelist->add_tile(&str.tile, fulltile ? (str.w/16_zf).getCeil() : 2,
6871 fulltile ? (str.h/16_zf).getCeil() : 2, fmt::format("{} (BG): '{}'", q, util::snip(str.s,100)));
6872 movelist->add_tile(&str.portrait_tile, str.portrait_tw, str.portrait_th,
6873 fmt::format("{} (Port.): '{}'", q, util::snip(str.s,100)));
6874 }
6875 if(!every_proc && !movelist->check_prot())
6876 return false;
6877 }
6878
6879 if(source_process) //Apply the 'diff' value to all moved tiles
6880 storage.redo();
6881 if(every_proc)
6882 for(auto &list : vec)
6883 for(auto &ref : list->move_refs)
6884 ref->forEach(every_proc);
6885 return true;
6886 }
6887 bool handle_tile_move(TileMoveProcess dest_process)
6888 {
6889 return _handle_tile_move(dest_process, nullopt, 0);
6890 }
6891 bool handle_tile_move(TileMoveProcess dest_process, TileMoveProcess source_process, int diff, TileMoveUndo& on_undo)
6892 {
6893 return _handle_tile_move(dest_process, source_process, diff, &on_undo);
6894 }
6895 void for_every_used_tile(std::function<void(int32_t)> proc)
6896 {
6897 reset_combo_animations();
6898 reset_combo_animations2();
6899 TileMoveProcess all_tiles {.rect = false, ._first = 0, ._last = NEWMAXTILES-1};
6900 _handle_tile_move(all_tiles, nullopt, 0, nullptr, proc, TileMoveList::Mode::CHECK_ALL);
6901 }
6902
6903 bool _handle_combo_move(ComboMoveProcess dest_process, optional<ComboMoveProcess> source_process, int diff, ComboMoveUndo* on_undo)
6904 {
6905 bool BSZ2 = get_qr(qr_BSZELDA);
6906 bool move = source_process.has_value();
6907 ComboMoveUndo local_undo;
6908 ComboMoveUndo& storage = on_undo ? *on_undo : local_undo;
6909 auto& vec = storage.vec;
6910 auto& combo_links = storage.combo_links;
6911 storage.diff = diff;
6912 storage.state = false;
6913 //Combo relative links
6914 {
6915 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6916 {
6917 newcombo& cmb = combobuf[q];
6918 if(cmb.trigchange)
6919 combo_links.add_to(q, q+cmb.trigchange);
6920 bool next = cmb.flag == mfSECRETSNEXT;
6921 switch(cmb.type)
6922 {
6923 case cPOUND:
6924 case cLOCKBLOCK: case cLOCKBLOCK2:
6925 case cBOSSLOCKBLOCK: case cBOSSLOCKBLOCK2:
6926 case cCHEST: case cCHEST2:
6927 case cLOCKEDCHEST: case cLOCKEDCHEST2:
6928 case cBOSSCHEST: case cBOSSCHEST2:
6929 case cSTEP: case cSTEPSAME: case cSTEPALL: case cSTEPCOPY:
6930 case cSLASHNEXT: case cSLASHNEXTITEM: case cBUSHNEXT:
6931 case cSLASHNEXTTOUCHY: case cSLASHNEXTITEMTOUCHY: case cBUSHNEXTTOUCHY:
6932 case cTALLGRASSNEXT: case cCRUMBLE:
6933 next = true;
6934 break;
6935 case cCSWITCH: case cCSWITCHBLOCK:
6936 combo_links.add_to(q, q+cmb.attributes[0]);
6937 break;
6938 case cLIGHTTARGET:
6939 if(cmb.usrflags & cflag1)
6940 combo_links.add_to(q, q-1);
6941 else next = true;
6942 break;
6943 case cSTEPSFX:
6944 if((cmb.usrflags&(cflag1|cflag3)) == cflag1)
6945 next = true;
6946 break;
6947 }
6948 if(next)
6949 combo_links.add_to(q, q+1);
6950 }
6951 }
6952
6953 //This function is expensive! Any optimizations possible should be made. -Em
6954
6955 //OPT: Check for a 0-val preemptively, to avoid processing the fmt::format strings
6956 #define ADDC(ptr, ...) \
6957 if(*ptr) movelist->add_combo(ptr, __VA_ARGS__);
6958 #define ADDC_10k(ptr, ...) \
6959 if(*ptr) movelist->add_combo_10k(ptr, __VA_ARGS__);
6960 //Combos
6961 {
6962 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
6963 combo_links, dest_process, source_process,
6964 move
6965 ? "The combos used by the following combos will be partially cleared by the move."
6966 : "The combos used by the following combos will be partially or completely overwritten by this process."
6967 ));
6968 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6969 {
6970 newcombo& cmb = combobuf[q];
6971 auto lbl = fmt::format("{}{}", q, cmb.label.empty() ? ""
6972 : fmt::format(" ({})", cmb.label));
6973 ADDC(&cmb.nextcombo, fmt::format("{} - Combo Cycle", lbl));
6974 ADDC(&cmb.liftcmb, fmt::format("{} - Lift Combo", lbl));
6975 ADDC(&cmb.liftundercmb, fmt::format("{} - Lift Undercombo", lbl));
6976 ADDC(&cmb.prompt_cid, fmt::format("{} - Triggers ButtonPrompt", lbl));
6977
6978 //type-specific
6979 char const* type_name = ZI.getComboTypeName(cmb.type);
6980 switch(cmb.type)
6981 {
6982 case cLOCKEDCHEST: case cBOSSCHEST:
6983 if(cmb.usrflags & cflag13)
6984 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
6985 [[fallthrough]];
6986 case cCHEST:
6987 if(cmb.usrflags & cflag13)
6988 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
6989 break;
6990 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
6991 if(cmb.usrflags & cflag13)
6992 {
6993 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
6994 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
6995 }
6996 break;
6997 case cSIGNPOST:
6998 if(cmb.usrflags & cflag13)
6999 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7000 break;
7001 case cBUTTONPROMPT:
7002 if(cmb.usrflags & cflag13)
7003 ADDC_10k(&cmb.attributes[0], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7004 break;
7005 }
7006 }
7007
7008 if(!movelist->check_prot())
7009 return false;
7010 }
7011 //Door Combo Sets
7012 {
7013 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7014 combo_links, dest_process, source_process,
7015 move
7016 ? "The combos used by the following screens will be partially cleared by the move."
7017 : "The combos used by the following screens will be partially or completely overwritten by this process."
7018 ));
7019 static const char* door_names[9] = {
7020 "Wall", "Locked", "Shuttered", "Boss", "Bombed", "Open", "Unlocked", "Open Shuttered", "Open Boss"
7021 };
7022 for(int32_t i=0; i<MAXDOORCOMBOSETS; i++)
7023 {
7024 auto& dcs = DoorComboSets[i];
7025 for(int32_t j=0; j<9; j++)
7026 {
7027 if(j<4)
7028 {
7029 ADDC(&dcs.walkthroughcombo[j], fmt::format("{} ({}): Walk-Through {}", i, dcs.name, j));
7030
7031 if(j<3)
7032 {
7033 if(j<2)
7034 {
7035 ADDC(&dcs.bombdoorcombo_u[j], fmt::format("{} ({}): Unused? bombdoorcombo_u {}", i, dcs.name, j));
7036 ADDC(&dcs.bombdoorcombo_d[j], fmt::format("{} ({}): Unused? bombdoorcombo_d {}", i, dcs.name, j));
7037 }
7038 ADDC(&dcs.bombdoorcombo_l[j], fmt::format("{} ({}): Unused? bombdoorcombo_l {}", i, dcs.name, j));
7039 ADDC(&dcs.bombdoorcombo_r[j], fmt::format("{} ({}): Unused? bombdoorcombo_r {}", i, dcs.name, j));
7040 }
7041 }
7042
7043 for(int32_t k=0; k<6; k++)
7044 {
7045 if(k<4)
7046 {
7047 ADDC(&dcs.doorcombo_u[j][k], fmt::format("{} ({}): Top, {} #{}", i, dcs.name, door_names[j], k));
7048 ADDC(&dcs.doorcombo_d[j][k], fmt::format("{} ({}): Bottom, {} #{}", i, dcs.name, door_names[j], k));
7049 }
7050
7051 ADDC(&dcs.doorcombo_l[j][k], fmt::format("{} ({}): Left, {} #{}", i, dcs.name, door_names[j], k));
7052 ADDC(&dcs.doorcombo_r[j][k], fmt::format("{} ({}): Right, {} #{}", i, dcs.name, door_names[j], k));
7053 }
7054 }
7055 }
7056
7057 if(!movelist->check_prot())
7058 return false;
7059 }
7060 //Combo Pools
7061 {
7062 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7063 combo_links, dest_process, source_process,
7064 move
7065 ? "The combos used by the following combo pools will be partially cleared by the move."
7066 : "The combos used by the following combo pools will be partially or completely overwritten by this process."
7067 ));
7068 for(auto q = 0; q < MAXCOMBOPOOLS; ++q)
7069 {
7070 combo_pool& pool = combo_pools[q];
7071 int idx = 0;
7072 for(cpool_entry& cp : pool.combos)
7073 ADDC(&cp.cid, fmt::format("{} index {}", q, idx++));
7074 }
7075
7076 if(!movelist->check_prot())
7077 return false;
7078 }
7079 //Auto Combos
7080 {
7081 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7082 combo_links, dest_process, source_process,
7083 move
7084 ? "The combos used by the following autocombos will be partially cleared by the move."
7085 : "The combos used by the following autocombos will be partially or completely overwritten by this process."
7086 ));
7087 for (auto q = 0; q < MAXAUTOCOMBOS; ++q)
7088 {
7089 combo_auto& cauto = combo_autos[q];
7090 int idx = 0;
7091 for (autocombo_entry& ac : cauto.combos)
7092 ADDC(&ac.cid, fmt::format("{} index {}", q, idx++));
7093 ADDC(&cauto.cid_erase, fmt::format("{} Erase Combo", q));
7094 ADDC(&cauto.cid_display, fmt::format("{} Display Combo", q));
7095 }
7096
7097 if(!movelist->check_prot())
7098 return false;
7099 }
7100 //Combo Aliases
7101 {
7102 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7103 combo_links, dest_process, source_process,
7104 move
7105 ? "The combos used by the following aliases will be partially cleared by the move."
7106 : "The combos used by the following aliases will be partially or completely overwritten by this process."
7107 ));
7108 for(int32_t i=0; i<MAXCOMBOALIASES; i++)
7109 {
7110 //dimensions are 1 less than you would expect -DD
7111 int32_t count=(comboa_lmasktotal(combo_aliases[i].layermask)+1)*(combo_aliases[i].width+1)*(combo_aliases[i].height+1);
7112
7113 for(int32_t j=0; j<count; j++)
7114 {
7115 ADDC(&combo_aliases[i].combos[j], fmt::format("{} index {}", i, j));
7116 }
7117 }
7118
7119 if(!movelist->check_prot())
7120 return false;
7121 }
7122 //Favorite Combos
7123 {
7124 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7125 combo_links, dest_process, source_process,
7126 move
7127 ? "The combos used by the following favorite combos will be partially cleared by the move."
7128 : "The combos used by the following favorite combos will be partially or completely overwritten by this process."
7129 ));
7130 for(int32_t i=0; i<MAXFAVORITECOMBOS; i++)
7131 {
7132 if(favorite_combo_modes[i] != dm_normal) //don't hit pools/aliases/autos, only combos!
7133 continue;
7134 ADDC(&favorite_combos[i], fmt::format("Favorite {}", i));
7135 }
7136
7137 if(!movelist->check_prot())
7138 return false;
7139 }
7140 //Bottle Shops
7141 {
7142 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7143 combo_links, dest_process, source_process,
7144 move
7145 ? "The combos used by the following bottle shops will be partially cleared by the move."
7146 : "The combos used by the following bottle shops will be partially or completely overwritten by this process."
7147 ));
7148 for(auto q = 0; q < 256; ++q)
7149 for(auto p = 0; p < 3; ++p)
7150 ADDC(&QMisc.bottle_shop_types[q].comb[p], fmt::format("{} slot {}", q, p));
7151
7152 if(!movelist->check_prot())
7153 return false;
7154 }
7155 //Screens //EXPENSIVE! DO THIS LAST!
7156 {
7157 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7158 combo_links, dest_process, source_process,
7159 move
7160 ? "The combos used by the following screens will be partially cleared by the move."
7161 : "The combos used by the following screens will be partially or completely overwritten by this process."
7162 ));
7163
7164 for(int32_t i=0; i<map_count && i<MAXMAPS; i++)
7165 {
7166 for(int32_t j=0; j<MAPSCRS; j++)
7167 {
7168 mapscr& scr = TheMaps[i*MAPSCRS+j];
7169
7170 if(!(scr.valid&mVALID))
7171 continue;
7172
7173 ADDC(&scr.undercombo, fmt::format("{}x{:02X} - UnderCombo", i, j));
7174 for(int32_t k=0; k<176; k++)
7175 ADDC(&scr.data[k], fmt::format("{}x{:02X} - Pos {}", i, j, k));
7176
7177 for(int32_t k=0; k<128; k++)
7178 ADDC(&scr.secretcombo[k], fmt::format("{}x{:02X} - SecretCombo {}", i, j, k));
7179
7180 word maxffc = scr.numFFC();
7181 for(word k=0; k<maxffc; k++)
7182 {
7183 ffcdata& ffc = scr.ffcs[k];
7184 ADDC(&ffc.data, fmt::format("{}x{:02X} - FFC {}", i, j, k+1));
7185 }
7186 }
7187 }
7188
7189 if(!movelist->check_prot())
7190 return false;
7191 }
7192 if(source_process) //Apply the 'diff' value to all moved combos
7193 storage.redo();
7194 return true;
7195 }
7196
7197 bool handle_combo_move(ComboMoveProcess dest_process)
7198 {
7199 return _handle_combo_move(dest_process, nullopt, 0, nullptr);
7200 }
7201 bool handle_combo_move(ComboMoveProcess dest_process, ComboMoveProcess source_process, int diff, ComboMoveUndo& on_undo)
7202 {
7203 return _handle_combo_move(dest_process, source_process, diff, &on_undo);
7204 }
7205 void register_used_tiles()
7206 {
7207 memset(used_tile_table, 0, sizeof(used_tile_table));
7208 for_every_used_tile([&](int tile)
7209 {
7210 used_tile_table[tile] = true;
7211 });
7212 }
7213
7214 bool overlay_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move, int32_t cs, bool backwards)
7215 {
7216 bool ctrl=(CHECK_CTRL_CMD);
7217 bool copied=false;
7218 copied=overlay_tiles_united(tile,tile2,copy,copycnt,rect_sel,move,cs,backwards);
7219
7220 if(copied)
7221 {
7222 saved=false;
7223 }
7224
7225 return copied;
7226 }
7227
7228 bool overlay_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move, int32_t cs, bool backwards)
7229 {
7230 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7231 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7232
7233 // if tile>tile2 then swap them
7234 if(tile>tile2)
7235 {
7236 zc_swap(tile, tile2);
7237 }
7238
7239 // alt=copy from right
7240 // shift=copy from bottom
7241
7242 int32_t copies=copycnt;
7243 int32_t dest_first=tile;
7244 int32_t dest_last=tile2;
7245 int32_t src_first=copy;
7246 int32_t src_last=copy+copies-1;
7247
7248 int32_t dest_top=0;
7249 int32_t dest_bottom=0;
7250 int32_t src_top=0;
7251 int32_t src_bottom=0;
7252 int32_t src_left=0, src_right=0;
7253 int32_t src_width=0, src_height=0;
7254 int32_t dest_left=0, dest_right=0;
7255 int32_t dest_width=0, dest_height=0;
7256 int32_t rows=0, cols=0;
7257
7258 if(rect)
7259 {
7260 dest_top=TILEROW(dest_first);
7261 dest_bottom=TILEROW(dest_last);
7262 src_top=TILEROW(src_first);
7263 src_bottom=TILEROW(src_last);
7264
7265 src_left= zc_min(TILECOL(src_first),TILECOL(src_last));
7266 src_right=zc_max(TILECOL(src_first),TILECOL(src_last));
7267 src_first=(src_top * TILES_PER_ROW)+src_left;
7268 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7269
7270 dest_left= zc_min(TILECOL(dest_first),TILECOL(dest_last));
7271 dest_right=zc_max(TILECOL(dest_first),TILECOL(dest_last));
7272 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7273 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7274
7275 //if no dest range set, then set one
7276 if((dest_first==dest_last)&&(src_first!=src_last))
7277 {
7278 if(alt)
7279 {
7280 dest_left=dest_right-(src_right-src_left);
7281 }
7282 else
7283 {
7284 dest_right=dest_left+(src_right-src_left);
7285 }
7286
7287 if(shift)
7288 {
7289 dest_top=dest_bottom-(src_bottom-src_top);
7290 }
7291 else
7292 {
7293 dest_bottom=dest_top+(src_bottom-src_top);
7294 }
7295
7296 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7297 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7298 }
7299 else
7300 {
7301 if(dest_right-dest_left<src_right-src_left) //destination is shorter than source
7302 {
7303 if(alt) //copy from right tile instead of left
7304 {
7305 src_left=src_right-(dest_right-dest_left);
7306 }
7307 else //copy from left tile
7308 {
7309 src_right=src_left+(dest_right-dest_left);
7310 }
7311 }
7312 else if(dest_right-dest_left>src_right-src_left) //destination is longer than source
7313 {
7314 if(alt) //copy from right tile instead of left
7315 {
7316 dest_left=dest_right-(src_right-src_left);
7317 }
7318 else //copy from left tile
7319 {
7320 dest_right=dest_left+(src_right-src_left);
7321 }
7322 }
7323
7324 if(dest_bottom-dest_top<src_bottom-src_top) //destination is shorter than source
7325 {
7326 if(shift) //copy from bottom tile instead of top
7327 {
7328 src_top=src_bottom-(dest_bottom-dest_top);
7329 }
7330 else //copy from top tile
7331 {
7332 src_bottom=src_top+(dest_bottom-dest_top);
7333 }
7334 }
7335 else if(dest_bottom-dest_top>src_bottom-src_top) //destination is longer than source
7336 {
7337 if(shift) //copy from bottom tile instead of top
7338 {
7339 dest_top=dest_bottom-(src_bottom-src_top);
7340 }
7341 else //copy from top tile
7342 {
7343 dest_bottom=dest_top+(src_bottom-src_top);
7344 }
7345 }
7346
7347 src_first=(src_top * TILES_PER_ROW)+src_left;
7348 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7349 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7350 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7351 }
7352
7353 cols=src_right-src_left+1;
7354 rows=src_bottom-src_top+1;
7355
7356 dest_width=dest_right-dest_left+1;
7357 dest_height=dest_bottom-dest_top+1;
7358 src_width=src_right-src_left+1;
7359 src_height=src_bottom-src_top+1;
7360
7361 }
7362 else //!rect
7363 {
7364 //if no dest range set, then set one
7365 if((dest_first==dest_last)&&(src_first!=src_last))
7366 {
7367 if(alt)
7368 {
7369 dest_first=dest_last-(src_last-src_first);
7370 }
7371 else
7372 {
7373 dest_last=dest_first+(src_last-src_first);
7374 }
7375 }
7376 else
7377 {
7378 if(dest_last-dest_first<src_last-src_first) //destination is shorter than source
7379 {
7380 if(alt) //copy from last tile instead of first
7381 {
7382 src_first=src_last-(dest_last-dest_first);
7383 }
7384 else //copy from first tile
7385 {
7386 src_last=src_first+(dest_last-dest_first);
7387 }
7388 }
7389 else if(dest_last-dest_first>src_last-src_first) //destination is longer than source
7390 {
7391 if(alt) //copy from last tile instead of first
7392 {
7393 dest_first=dest_last-(src_last-src_first);
7394 }
7395 else //copy from first tile
7396 {
7397 dest_last=dest_first+(src_last-src_first);
7398 }
7399 }
7400 }
7401
7402 copies=dest_last-dest_first+1;
7403 }
7404
7405
7406
7407 char buf2[80], buf3[80], buf4[80];
7408 sprintf(buf2, " ");
7409 sprintf(buf3, " ");
7410 sprintf(buf4, " ");
7411
7412 // warn if range extends beyond last tile
7413 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7414
7415 if(dest_last>=NEWMAXTILES)
7416 {
7417 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7418 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7419 return false;
7420 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7421 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7422 // {
7423 // return false;
7424 // }
7425 }
7426
7427
7428 TileMoveUndo on_undo;
7429 // Overwrite warnings
7430 TileMoveProcess dest{rect, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last};
7431 if(move)
7432 {
7433 TileMoveProcess src{rect, src_left, src_top, src_width, src_height, src_first, src_last};
7434 if(!handle_tile_move(dest, src, dest_first-src_first, on_undo))
7435 return false;
7436 }
7437 else
7438 {
7439 if(!handle_tile_move(dest))
7440 return false;
7441 }
7442 // copy tiles and delete if needed (move)
7443
7444 {
7445 go_tiles();
7446
7447 int32_t diff=dest_first-src_first;
7448
7449 if(rect)
7450 {
7451 for(int32_t r=0; r<rows; ++r)
7452 {
7453 for(int32_t c=0; c<cols; ++c)
7454 {
7455 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
7456 int32_t st=(src_first+((r*TILES_PER_ROW)+c));
7457
7458 if(dt>=NEWMAXTILES)
7459 continue;
7460
7461 overlay_tile(newtilebuf,dt,st,cs,backwards);
7462
7463 }
7464 }
7465 }
7466 else
7467 {
7468 for(int32_t c=0; c<copies; ++c)
7469 {
7470 int32_t dt=(dest_first+c);
7471 int32_t st=(src_first+c);
7472
7473 if(dt>=NEWMAXTILES)
7474 continue;
7475
7476 overlay_tile(newtilebuf,dt,st,cs,backwards);
7477
7478 if(move)
7479 {
7480 if(st<dest_first||st>(dest_first+c-1))
7481 reset_tile(newtilebuf, st, tf4Bit);
7482 }
7483 }
7484 }
7485 }
7486
7487 //now that tiles have moved, fix these buffers -DD
7488 register_blank_tiles();
7489 register_used_tiles();
7490
7491 if(move)
7492 last_tile_move_list = std::move(on_undo);
7493 return true;
7494 }
7495 //
7496 bool do_movetile_united(tile_move_data const& tmd)
7497 {
7498 char buf2[80], buf3[80], buf4[80];
7499 sprintf(buf2, " ");
7500 sprintf(buf3, " ");
7501 sprintf(buf4, " ");
7502
7503 // warn if range extends beyond last tile
7504 sprintf(buf4, "Some tiles will not be %s", tmd.move?"moved.":"copied.");
7505
7506 if(tmd.dest_last>=NEWMAXTILES)
7507 {
7508 sprintf(buf4, "%s operation cancelled.", tmd.move?"Move":"Copy");
7509 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7510 return false;
7511 }
7512
7513 TileMoveUndo on_undo;
7514 // Overwrite warnings
7515 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7516 if(tmd.move)
7517 {
7518 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7519 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7520 return false;
7521 }
7522 else
7523 {
7524 if(!handle_tile_move(dest))
7525 return false;
7526 }
7527
7528 // copy tiles and delete if needed (tmd.move)
7529 {
7530 go_tiles();
7531
7532 if(tmd.rect)
7533 {
7534 for(int32_t r=0; r<tmd.rows; ++r)
7535 {
7536 for(int32_t c=0; c<tmd.cols; ++c)
7537 {
7538 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7539 int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7540
7541 if(dt>=NEWMAXTILES)
7542 continue;
7543
7544 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7545
7546 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7547 {
7548 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7549 }
7550
7551 if(tmd.move)
7552 {
7553 if((st<tmd.dest_first||st>tmd.dest_first+((tmd.rows-1)*TILES_PER_ROW)+(tmd.cols-1)))
7554 reset_tile(newtilebuf, st, tf4Bit);
7555 else
7556 {
7557 int32_t destLeft=tmd.dest_first%TILES_PER_ROW;
7558 int32_t destRight=(tmd.dest_first+tmd.cols-1)%TILES_PER_ROW;
7559 if(destLeft<=destRight)
7560 {
7561 if(st%TILES_PER_ROW<destLeft || st%TILES_PER_ROW>destRight)
7562 reset_tile(newtilebuf, st, tf4Bit);
7563 }
7564 else // Wrapped around
7565 {
7566 if(st%TILES_PER_ROW<destLeft && st%TILES_PER_ROW>destRight)
7567 reset_tile(newtilebuf, st, tf4Bit);
7568 }
7569 }
7570 }
7571 }
7572 }
7573 }
7574 else
7575 {
7576 for(int32_t c=0; c<tmd.copies; ++c)
7577 {
7578 int32_t dt=(tmd.dest_first+c);
7579 int32_t st=(tmd.src_first+c);
7580
7581 if(dt>=NEWMAXTILES)
7582 continue;
7583
7584 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7585
7586 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7587 {
7588 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7589 }
7590
7591 if(tmd.move)
7592 {
7593 if(st<tmd.dest_first||st>(tmd.dest_first+c-1))
7594 reset_tile(newtilebuf, st, tf4Bit);
7595 }
7596 }
7597 }
7598 }
7599
7600 //now that tiles have moved, fix these buffers -DD
7601 register_blank_tiles();
7602 register_used_tiles();
7603
7604 if(tmd.move)
7605 last_tile_move_list = std::move(on_undo);
7606 return true;
7607 }
7608
7609 bool copy_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7610 {
7611 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7612 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7613
7614 // if tile>tile2 then swap them
7615 if(tile>tile2)
7616 {
7617 zc_swap(tile, tile2);
7618 }
7619
7620 // alt=copy from right
7621 // shift=copy from bottom
7622 tile_move_data tmd;
7623
7624 tmd.copies=copycnt;
7625 tmd.dest_first=tile;
7626 tmd.dest_last=tile2;
7627 tmd.src_first=copy;
7628 tmd.src_last=copy+tmd.copies-1;
7629 tmd.rect = rect;
7630 tmd.move = move;
7631
7632 if(rect)
7633 {
7634 tmd.dest_top=TILEROW(tmd.dest_first);
7635 tmd.dest_bottom=TILEROW(tmd.dest_last);
7636 tmd.src_top=TILEROW(tmd.src_first);
7637 tmd.src_bottom=TILEROW(tmd.src_last);
7638
7639 tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7640 tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7641 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7642 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7643
7644 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7645 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7646 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7647 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7648
7649 //if no dest range set, then set one
7650 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7651 {
7652 if(alt)
7653 {
7654 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7655 }
7656 else
7657 {
7658 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7659 }
7660
7661 if(shift)
7662 {
7663 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7664 }
7665 else
7666 {
7667 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7668 }
7669
7670 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7671 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7672 }
7673 else
7674 {
7675 if(tmd.dest_right-tmd.dest_left<tmd.src_right-tmd.src_left) //destination is shorter than source
7676 {
7677 if(alt) //copy from right tile instead of left
7678 {
7679 tmd.src_left=tmd.src_right-(tmd.dest_right-tmd.dest_left);
7680 }
7681 else //copy from left tile
7682 {
7683 tmd.src_right=tmd.src_left+(tmd.dest_right-tmd.dest_left);
7684 }
7685 }
7686 else if(tmd.dest_right-tmd.dest_left>tmd.src_right-tmd.src_left) //destination is longer than source
7687 {
7688 if(alt) //copy from right tile instead of left
7689 {
7690 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7691 }
7692 else //copy from left tile
7693 {
7694 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7695 }
7696 }
7697
7698 if(tmd.dest_bottom-tmd.dest_top<tmd.src_bottom-tmd.src_top) //destination is shorter than source
7699 {
7700 if(shift) //copy from bottom tile instead of top
7701 {
7702 tmd.src_top=tmd.src_bottom-(tmd.dest_bottom-tmd.dest_top);
7703 }
7704 else //copy from top tile
7705 {
7706 tmd.src_bottom=tmd.src_top+(tmd.dest_bottom-tmd.dest_top);
7707 }
7708 }
7709 else if(tmd.dest_bottom-tmd.dest_top>tmd.src_bottom-tmd.src_top) //destination is longer than source
7710 {
7711 if(shift) //copy from bottom tile instead of top
7712 {
7713 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7714 }
7715 else //copy from top tile
7716 {
7717 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7718 }
7719 }
7720
7721 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7722 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7723 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7724 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7725 }
7726
7727 tmd.cols=tmd.src_right-tmd.src_left+1;
7728 tmd.rows=tmd.src_bottom-tmd.src_top+1;
7729
7730 tmd.dest_width=tmd.dest_right-tmd.dest_left+1;
7731 tmd.dest_height=tmd.dest_bottom-tmd.dest_top+1;
7732 tmd.src_width=tmd.src_right-tmd.src_left+1;
7733 tmd.src_height=tmd.src_bottom-tmd.src_top+1;
7734
7735 }
7736 else //!rect
7737 {
7738 //if no dest range set, then set one
7739 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7740 {
7741 if(alt)
7742 {
7743 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7744 }
7745 else
7746 {
7747 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7748 }
7749 }
7750 else
7751 {
7752 if(tmd.dest_last-tmd.dest_first<tmd.src_last-tmd.src_first) //destination is shorter than source
7753 {
7754 if(alt) //copy from last tile instead of first
7755 {
7756 tmd.src_first=tmd.src_last-(tmd.dest_last-tmd.dest_first);
7757 }
7758 else //copy from first tile
7759 {
7760 tmd.src_last=tmd.src_first+(tmd.dest_last-tmd.dest_first);
7761 }
7762 }
7763 else if(tmd.dest_last-tmd.dest_first>tmd.src_last-tmd.src_first) //destination is longer than source
7764 {
7765 if(alt) //copy from last tile instead of first
7766 {
7767 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7768 }
7769 else //copy from first tile
7770 {
7771 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7772 }
7773 }
7774 }
7775
7776 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7777 }
7778
7779 return do_movetile_united(tmd);
7780 }
7781
7782 //
7783
7784 bool copy_tiles_united_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7785 {
7786 assert(!move); //not implemented
7787
7788 // if tile>tile2 then swap them
7789 if(tile>tile2)
7790 {
7791 zc_swap(tile, tile2);
7792 }
7793
7794 tile_move_data tmd;
7795 tmd.copies=copycnt;
7796 tmd.dest_first=tile;
7797 tmd.dest_last=tile2;
7798 tmd.src_first=copy;
7799 tmd.src_last=copy+tmd.copies-1;
7800
7801
7802
7803 if(rect)
7804 {
7805 tmd.dest_top=TILEROW(tmd.dest_first);
7806 tmd.dest_bottom=TILEROW(tmd.dest_last);
7807 //tmd.src_top=TILEROW(tmd.src_first);
7808 //tmd.src_bottom=TILEROW(tmd.src_last);
7809
7810 //tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7811 //tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7812 //tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7813 //tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7814
7815 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7816 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7817 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7818 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7819
7820
7821
7822
7823 tmd.dest_width=tmd.dest_right-tmd.dest_left;
7824 tmd.dest_height=tmd.dest_bottom-tmd.dest_top;
7825
7826 tmd.cols=tmd.dest_width+1;
7827 tmd.rows=tmd.dest_height+1;
7828
7829 al_trace("tmd.rows: %d\n", tmd.rows);
7830 al_trace("tmd.cols: %d\n", tmd.cols);
7831
7832
7833 }
7834 else //!rect
7835 {
7836 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7837 }
7838
7839
7840
7841 char buf2[80], buf3[80], buf4[80];
7842 sprintf(buf2, " ");
7843 sprintf(buf3, " ");
7844 sprintf(buf4, " ");
7845
7846 // warn if range extends beyond last tile
7847 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7848
7849 if(tmd.dest_last>=NEWMAXTILES)
7850 {
7851 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7852 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7853 return false;
7854 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7855 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7856 // {
7857 // return false;
7858 // }
7859 }
7860
7861 TileMoveUndo on_undo;
7862 // Overwrite warnings
7863 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7864 if(tmd.move)
7865 {
7866 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7867 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7868 return false;
7869 }
7870 else
7871 {
7872 if(!handle_tile_move(dest))
7873 return false;
7874 }
7875
7876 // copy tiles and delete if needed (move)
7877
7878 {
7879 go_tiles();
7880
7881 int32_t diff=tmd.dest_first-tmd.src_first;
7882
7883 if(rect)
7884 {
7885 al_trace("floodfill, rect\n");
7886 al_trace("tmd.rows: %d\n", tmd.rows);
7887 al_trace("tmd.cols: %d\n", tmd.cols);
7888 for(int32_t r=0; r<tmd.rows; ++r)
7889 {
7890 for(int32_t c=0; c<tmd.cols; ++c)
7891 {
7892 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7893 //int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7894
7895 if(dt>=NEWMAXTILES)
7896 continue;
7897
7898 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
7899
7900 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
7901 {
7902 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
7903 }
7904 }
7905 }
7906 }
7907 else
7908 {
7909 for(int32_t c=0; c<tmd.copies; ++c)
7910 {
7911 int32_t dt=(tmd.dest_first+c);
7912 int32_t st=(tmd.src_first+c);
7913
7914 if(dt>=NEWMAXTILES)
7915 continue;
7916
7917 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
7918
7919 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
7920 {
7921 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
7922 }
7923
7924 }
7925 }
7926 }
7927
7928 //now that tiles have moved, fix these buffers -DD
7929 register_blank_tiles();
7930 register_used_tiles();
7931
7932 if(tmd.move)
7933 last_tile_move_list = std::move(on_undo);
7934 return true;
7935 }
7936 //
7937
7938 bool copy_tiles_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
7939 {
7940 al_trace("Floodfill Psste\n");
7941 bool ctrl=(CHECK_CTRL_CMD);
7942 bool copied=false;
7943 copied=copy_tiles_united_floodfill(tile,tile2,copy,copycnt,rect_sel,move);
7944
7945 if(copied)
7946 {
7947 if(!ctrl)
7948 {
7949 copy=-1;
7950 tile2=tile;
7951 }
7952
7953 saved=false;
7954 }
7955
7956 return copied;
7957 }
7958
7959 bool copy_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
7960 {
7961 bool ctrl=(CHECK_CTRL_CMD);
7962 bool copied=false;
7963 copied=copy_tiles_united(tile,tile2,copy,copycnt,rect_sel,move);
7964
7965 if(copied)
7966 {
7967 if(!ctrl)
7968 {
7969 copy=-1;
7970 tile2=tile;
7971 }
7972
7973 saved=false;
7974 }
7975
7976 return copied;
7977 }
7978
7979 bool scale_or_rotate_tiles(int32_t &tile, int32_t &tile2, int32_t &cs, bool rotate)
7980 {
7981 // if tile>tile2 then swap them
7982 if(tile>tile2)
7983 {
7984 zc_swap(tile, tile2);
7985 }
7986 int32_t src_top = TILEROW(tile);
7987 int32_t src_bottom = TILEROW(tile2);
7988 int32_t src_left = zc_min(TILECOL(tile),TILECOL(tile2));
7989 int32_t src_right = zc_max(TILECOL(tile),TILECOL(tile2));
7990 int32_t src_first = (src_top * TILES_PER_ROW)+src_left;
7991 int32_t src_last = (src_bottom*TILES_PER_ROW)+src_right;
7992
7993 int32_t src_width = src_right-src_left+1,
7994 src_height = src_bottom-src_top+1;
7995 int32_t dest_width = src_width, dest_height = src_height;
7996 zfix dest_rot = 0_zf;
7997 if(rotate)
7998 RotateTileDialog(&dest_width, &dest_height, &dest_rot).show();
7999 else
8000 ScaleTileDialog(&dest_width, &dest_height).show();
8001 if (rotate)
8002 {
8003 if (dest_rot == 0) return false;
8004 }
8005 else
8006 {
8007 if (dest_width == src_width && dest_height == src_height) return false; //no scaling
8008 }
8009 dest_width = vbound(dest_width, 1, 20);
8010 dest_height = vbound(dest_height, 1, 20);
8011
8012 int32_t dest_top = src_top;
8013 int32_t dest_bottom = src_top+dest_height-1;
8014 int32_t dest_left = src_left;
8015 int32_t dest_right = src_left+dest_width-1;
8016 int32_t dest_first = src_first;
8017 int32_t dest_last = (dest_bottom*TILES_PER_ROW)+dest_right;
8018
8019
8020 if(dest_last>=NEWMAXTILES)
8021 {
8022 InfoDialog("Destination Error", "The destination extends beyond the last available tile row. Scale operation cancelled.").show();
8023 return false;
8024 }
8025
8026 // Overwrite warnings
8027 if(!handle_tile_move({true, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last}))
8028 return false;
8029
8030 //Do the rotate
8031 {
8032 go_tiles();
8033
8034 int32_t diff=dest_first-src_first;
8035 BITMAP *srcbmp = create_bitmap_ex(8,src_width*16,src_height*16),
8036 *destbmp = create_bitmap_ex(8,dest_width*16,dest_height*16);
8037 clear_bitmap(srcbmp); clear_bitmap(destbmp);
8038 overtileblock16(srcbmp, src_first, 0, 0, src_width, src_height, cs, 0);
8039 bool is8bit = newtilebuf[src_first].format == tf8Bit;
8040 if (rotate)
8041 {
8042 rotate_sprite(destbmp, srcbmp, 0, 0, ftofix(dest_rot * 0.7111111111111));
8043 }
8044 else
8045 {
8046 stretch_blit(srcbmp, destbmp, 0, 0, srcbmp->w, srcbmp->h,
8047 0, 0, destbmp->w, destbmp->h);
8048 }
8049 int32_t mhei = zc_max(src_height,dest_height),
8050 mwid = zc_max(src_width, dest_width);
8051 for(int32_t r=0; r<mhei; ++r)
8052 {
8053 for(int32_t c=0; c<mwid; ++c)
8054 {
8055 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
8056
8057 if(dt>=NEWMAXTILES)
8058 continue;
8059 if(r < dest_height && c < dest_width)
8060 {
8061 write_tile(newtilebuf, destbmp, dt, c*16, r*16, is8bit, false);
8062 }
8063 else reset_tile(newtilebuf, dt, tf4Bit);
8064 }
8065 }
8066 }
8067
8068 register_blank_tiles();
8069 register_used_tiles();
8070 return true;
8071 }
8072
8073 void copy_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool masscopy)
8074 {
8075 //these 2 shouldn't be needed, but just to be safe...
8076 reset_combo_animations();
8077 reset_combo_animations2();
8078
8079 if(tile2<tile)
8080 {
8081 zc_swap(tile,tile2);
8082 }
8083
8084 auto first = tile;
8085 auto last = masscopy ? tile2 : first + copycnt-1;
8086 if(!handle_combo_move({first,last}))
8087 return;
8088
8089 if(!masscopy)
8090 {
8091 if(tile==copy)
8092 {
8093 copy=-1;
8094 tile2=tile;
8095 return;
8096 }
8097
8098 // go_combos(); // commented because caller does it for us
8099 //if copying to an earlier combo, copy from left to right
8100 //otherwise, copy from right to left
8101 for(int32_t t=(tile<copy)?0:(copycnt-1); (tile<copy)?(t<copycnt):(t>=0); (tile<copy)?(t++):(t--))
8102 {
8103 if(tile+t < MAXCOMBOS)
8104 {
8105 combobuf[tile+t]=combobuf[copy+t];
8106 }
8107 }
8108
8109 copy=-1;
8110 tile2=tile;
8111 saved=false;
8112 }
8113 else
8114 {
8115 // go_combos();
8116 int32_t src=copy, dest=tile;
8117
8118 do
8119 {
8120 combobuf[dest]=combobuf[src];
8121 ++src;
8122 ++dest;
8123
8124 if((src-copy)==copycnt) src=copy;
8125 }
8126 while(dest<=tile2);
8127
8128 copy=-1;
8129 tile2=tile;
8130 saved=false;
8131 }
8132
8133 setup_combo_animations();
8134 setup_combo_animations2();
8135 }
8136
8137 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing)
8138 {
8139 reset_combo_animations();
8140 reset_combo_animations2();
8141 go_combos();
8142
8143 auto diff = cmd.tile - cmd.copy1;
8144 if(is_undoing)
8145 on_undo.undo();
8146 else if(!handle_combo_move({cmd.tile,cmd.tile+cmd.copycnt-1},{cmd.copy1,cmd.copy1+cmd.copycnt-1}, diff, on_undo))
8147 return false;
8148
8149 for(int32_t t=(cmd.tile<cmd.copy1)?0:(cmd.copycnt-1); (cmd.tile<cmd.copy1)?(t<cmd.copycnt):(t>=0); (cmd.tile<cmd.copy1)?(t++):(t--))
8150 {
8151 if(cmd.tile+t < MAXCOMBOS)
8152 {
8153 combobuf[cmd.tile+t]=combobuf[cmd.copy1+t];
8154 clear_combo(cmd.copy1+t);
8155 }
8156 }
8157
8158 setup_combo_animations();
8159 setup_combo_animations2();
8160 saved=false;
8161 return true;
8162 }
8163
8164 void move_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt)
8165 {
8166 if(tile2<tile)
8167 {
8168 zc_swap(tile,tile2);
8169 }
8170
8171 if(tile==copy)
8172 {
8173 copy=-1;
8174 tile2=tile;
8175 return;
8176 }
8177
8178 combo_move_data cmd;
8179 cmd.tile = tile;
8180 cmd.tile2 = tile2;
8181 cmd.copy1 = copy;
8182 cmd.copycnt = copycnt;
8183
8184 ComboMoveUndo on_undo;
8185 if(!do_movecombo(cmd, on_undo))
8186 return;
8187 last_combo_move_list = std::move(on_undo);
8188 copy=-1;
8189 tile2=tile;
8190 }
8191
8192 void do_delete_tiles(int32_t firsttile, int32_t lasttile, bool rect_sel)
8193 {
8194 if(firsttile > lasttile)
8195 zc_swap(firsttile,lasttile);
8196 int32_t coldiff = 0;
8197 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8198 {
8199 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8200 firsttile-=coldiff;
8201 lasttile+=coldiff;
8202 }
8203 for(int32_t t=firsttile; t<=lasttile; ++t)
8204 if(!rect_sel ||
8205 ((TILECOL(t)>=TILECOL(firsttile)) &&
8206 (TILECOL(t)<=TILECOL(lasttile))))
8207 reset_tile(newtilebuf, t, tf4Bit);
8208 saved=false;
8209 register_blank_tiles();
8210 }
8211
8212 void delete_tiles(int32_t &tile,int32_t &tile2,bool rect_sel)
8213 {
8214 char buf[40];
8215
8216 if(tile==tile2)
8217 {
8218 sprintf(buf,"Delete tile %d?",tile);
8219 }
8220 else
8221 {
8222 sprintf(buf,"Delete tiles %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
8223 }
8224
8225 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8226 {
8227 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8228
8229 go_tiles();
8230
8231 //if copying to an earlier tile, copy from left to right
8232 //otherwise, copy from right to left
8233 do_delete_tiles(firsttile, lasttile, rect_sel);
8234
8235 tile=tile2=zc_min(tile,tile2);
8236 saved=false;
8237 register_blank_tiles();
8238 }
8239 }
8240
8241 void overlay_tile2(int32_t dest,int32_t src,int32_t cs,bool backwards)
8242 {
8243 byte buf[256];
8244 go_tiles();
8245
8246 unpack_tile(newtilebuf, dest, 0, false);
8247
8248 for(int32_t i=0; i<256; i++)
8249 buf[i] = unpackbuf[i];
8250
8251 unpack_tile(newtilebuf, src, 0, false);
8252
8253 if(newtilebuf[src].format>tf4Bit)
8254 {
8255 cs=0;
8256 }
8257
8258 cs &= 15;
8259 cs <<= CSET_SHFT;
8260
8261 for(int32_t i=0; i<256; i++)
8262 {
8263 if(backwards)
8264 {
8265 if(!buf[i])
8266 {
8267 buf[i] = unpackbuf[i]+cs;
8268 }
8269 }
8270 else
8271 {
8272 if(unpackbuf[i])
8273 {
8274 buf[i] = unpackbuf[i]+cs;
8275 }
8276 }
8277 }
8278
8279 pack_tile(newtilebuf, buf,dest);
8280 saved=false;
8281 }
8282
8283 void mass_overlay_tile(int32_t dest1, int32_t dest2, int32_t src, int32_t cs, bool backwards, bool rect_sel)
8284 {
8285 //byte buf[256];
8286 go_tiles();
8287
8288 if(!rect_sel)
8289 {
8290 for(int32_t d=dest1; d <= dest2; ++d)
8291 {
8292 /*unpack_tile(newtilebuf, d, 0, false);
8293
8294 for(int32_t i=0; i<256; i++)
8295 {
8296 if(!backwards)
8297 {
8298 if(!buf[i])
8299 {
8300 buf[i] = unpackbuf[i] + cs;
8301 }
8302 }
8303 else
8304 {
8305 if(unpackbuf[i])
8306 {
8307 buf[i] = unpackbuf[i] + cs;
8308 }
8309 }
8310 }
8311
8312 pack_tile(newtilebuf, buf,d);
8313 */
8314
8315 overlay_tile(newtilebuf,d,src,cs,backwards);
8316
8317 if(!blank_tile_table[src])
8318 {
8319 blank_tile_table[d]=false;
8320 }
8321 }
8322 }
8323 else
8324 {
8325 int32_t rmin=zc_min(TILEROW(dest1),TILEROW(dest2));
8326 int32_t rmax=zc_max(TILEROW(dest1),TILEROW(dest2));
8327 int32_t cmin=zc_min(TILECOL(dest1),TILECOL(dest2));
8328 int32_t cmax=zc_max(TILECOL(dest1),TILECOL(dest2));
8329 int32_t d=0;
8330
8331 for(int32_t j=cmin; j<=cmax; ++j)
8332 {
8333 for(int32_t k=rmin; k<=rmax; ++k)
8334 {
8335 d=j+TILES_PER_ROW*k;
8336 /*unpack_tile(newtilebuf, d, 0, false);
8337
8338 for(int32_t i=0; i<256; i++)
8339 {
8340 if(!backwards)
8341 {
8342 if(!buf[i])
8343 {
8344 buf[i] = unpackbuf[i] + cs;
8345 }
8346 }
8347 else
8348 {
8349 if(unpackbuf[i])
8350 {
8351 buf[i] = unpackbuf[i] + cs;
8352 }
8353 }
8354 }
8355
8356 pack_tile(newtilebuf, buf,d);
8357 */
8358
8359 overlay_tile(newtilebuf,d,src,cs,backwards);
8360
8361 if(!blank_tile_table[src])
8362 {
8363 blank_tile_table[d]=false;
8364 }
8365 }
8366 }
8367 }
8368
8369 return;
8370 }
8371
8372 void sel_tile(int32_t &tile, int32_t &tile2, int32_t &first, int32_t type, int32_t s)
8373 {
8374 tile+=s;
8375 bound(tile,0,NEWMAXTILES-1);
8376
8377 if(type!=0 || !(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
8378 tile2 = tile;
8379
8380 first = tile - (tile%TILES_PER_PAGE);
8381 }
8382
8383 void convert_tile(int32_t t, int32_t bp2, int32_t cs, bool shift, bool alt)
8384 {
8385 int32_t cst;
8386
8387 switch(bp2)
8388 {
8389 case tf4Bit:
8390 switch(newtilebuf[t].format)
8391 {
8392 case tf4Bit:
8393 //already in the right format
8394 break;
8395
8396 case tf8Bit:
8397 unpack_tile(newtilebuf, t, 0, true);
8398
8399 if(alt) //reduce
8400 {
8401 for(int32_t i=0; i<256; i++)
8402 {
8403 if(!shift||unpackbuf[i]!=0)
8404 {
8405 unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
8406 }
8407 }
8408 }
8409 else //truncate
8410 {
8411 for(int32_t i=0; i<256; i++)
8412 {
8413 unpackbuf[i]&=15;
8414 }
8415 }
8416
8417 reset_tile(newtilebuf, t, tf4Bit);
8418 pack_tile(newtilebuf, unpackbuf, t);
8419 break;
8420 }
8421
8422 break;
8423
8424 case tf8Bit:
8425 switch(newtilebuf[t].format)
8426 {
8427 case tf4Bit:
8428 unpack_tile(newtilebuf, t, 0, true);
8429 cst = cs&15;
8430 cst <<= CSET_SHFT;
8431
8432 for(int32_t i=0; i<256; i++)
8433 {
8434 if(!shift||unpackbuf[i]!=0)
8435 {
8436 unpackbuf[i]+=cst;
8437 }
8438 }
8439
8440 reset_tile(newtilebuf, t, tf8Bit);
8441 pack_tile(newtilebuf, unpackbuf, t);
8442 break;
8443
8444 case tf8Bit:
8445 //already in the right format
8446 break;
8447 }
8448
8449 break;
8450 }
8451 }
8452
8453 static DIALOG create_relational_tiles_dlg[] =
8454 {
8455 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
8456 8 { jwin_win_proc, 0, 0, 160, 92, vc(0), vc(11), 0, D_EXIT, 0, 0, (void *) "Tile Setup", NULL, NULL },
8457 8 { jwin_rtext_proc, 74, 28, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Frames:", NULL, NULL },
8458 8 { jwin_edit_proc, 78, 24, 48, 16, 0, 0, 0, 0, 6, 0, NULL, NULL, NULL },
8459 8 { jwin_radio_proc, 8, 44, 64, 9, vc(14), vc(1), 0, D_SELECTED, 0, 0, (void *) "Relational", NULL, NULL },
8460 8 { jwin_radio_proc, 68, 44, 64, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "Dungeon Carving", NULL, NULL },
8461 8 { jwin_button_proc, 10, 66, 61, 21, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
8462 8 { jwin_button_proc, 90, 66, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
8463 8 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
8464 8 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
8465 };
8466
8467 void draw_tile_list_window()
8468 {
8469 int32_t w = 640;
8470 int32_t h = 480;
8471
8472 int32_t window_xofs=(zq_screen_w-w-12)>>1;
8473 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
8474 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
8475 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
8476
8477 FONT *oldfont = font;
8478 font = get_zc_font(font_lfont);
8479 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Tile", true);
8480 font=oldfont;
8481 return;
8482 }
8483
8484 void show_blank_tile(int32_t t)
8485 {
8486 char tbuf[80], tbuf2[80], tbuf3[80];
8487 sprintf(tbuf, "Tile is%s blank.", blank_tile_table[t]?"":" not");
8488 sprintf(tbuf2, "%c %c", blank_tile_quarters_table[t*4]?'X':'-', blank_tile_quarters_table[(t*4)+1]?'X':'-');
8489 sprintf(tbuf3, "%c %c", blank_tile_quarters_table[(t*4)+2]?'X':'-', blank_tile_quarters_table[(t*4)+3]?'X':'-');
8490 jwin_alert("Blank Tile Information",tbuf,tbuf2,tbuf3,"&OK",NULL,13,27,get_zc_font(font_lfont));
8491 }
8492
8493 void do_convert_tile(int32_t tile, int32_t tile2, int32_t cs, bool rect_sel, bool fourbit, bool shift, bool alt)
8494 {
8495 char buf[80];
8496 sprintf(buf, "Do you want to convert the selected %s to %d-bit color?", tile==tile2?"tile":"tiles",fourbit?4:8);
8497
8498 if(jwin_alert("Convert Tile?",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8499 {
8500 go_tiles();
8501 saved=false;
8502
8503 if(fourbit)
8504 {
8505 memset(cset_reduce_table, 0, 256);
8506 memset(col_diff,0,3*128);
8507 calc_cset_reduce_table(RAMpal, cs);
8508 }
8509
8510 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8511
8512 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8513 {
8514 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8515 firsttile-=coldiff;
8516 lasttile+=coldiff;
8517 }
8518
8519 for(int32_t t=firsttile; t<=lasttile; t++)
8520 if(!rect_sel ||
8521 ((TILECOL(t)>=TILECOL(firsttile)) &&
8522 (TILECOL(t)<=TILECOL(lasttile))))
8523 convert_tile(t, fourbit?tf4Bit:tf8Bit, cs, shift, alt);
8524
8525 tile=tile2=zc_min(tile,tile2);
8526 }
8527 }
8528
8529
8530 int32_t readtilefile(PACKFILE *f)
8531 {
8532 dword section_version=0;
8533 dword section_cversion=0;
8534 int32_t zversion = 0;
8535 int32_t zbuild = 0;
8536
8537 if(!p_igetl(&zversion,f))
8538 {
8539 return 0;
8540 }
8541 if(!p_igetl(&zbuild,f))
8542 {
8543 return 0;
8544 }
8545 if(!p_igetw(&section_version,f))
8546 {
8547 return 0;
8548 }
8549 if(!p_igetw(&section_cversion,f))
8550 {
8551 return 0;
8552 }
8553 al_trace("readoneweapon section_version: %d\n", section_version);
8554 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8555
8556 if ( zversion > ZELDA_VERSION )
8557 {
8558 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8559 return 0;
8560 }
8561
8562 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8563 {
8564 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8565 return 0;
8566
8567 }
8568 else
8569 {
8570 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8571 }
8572
8573 int32_t index = 0;
8574 int32_t count = 0;
8575
8576 //tile id
8577 if(!p_igetl(&index,f))
8578 {
8579 return 0;
8580 }
8581 al_trace("Reading tile: index(%d)\n", index);
8582
8583 //tile count
8584 if(!p_igetl(&count,f))
8585 {
8586 return 0;
8587 }
8588 al_trace("Reading tile: count(%d)\n", count);
8589
8590
8591
8592
8593 for ( int32_t tilect = 0; tilect < count; tilect++ )
8594 {
8595 byte *temp_tile = new byte[tilesize(tf32Bit)];
8596 byte format=tf4Bit;
8597 memset(temp_tile, 0, tilesize(tf32Bit));
8598 if(!p_getc(&format,f))
8599 {
8600 delete[] temp_tile;
8601 return 0;
8602 }
8603
8604
8605 if(!pfread(temp_tile,tilesize(format),f))
8606 {
8607 delete[] temp_tile;
8608 return 0;
8609 }
8610
8611 reset_tile(newtilebuf, index+(tilect), format);
8612 memcpy(newtilebuf[index+(tilect)].data,temp_tile,tilesize(newtilebuf[index+(tilect)].format));
8613 delete[] temp_tile;
8614 }
8615
8616
8617 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8618
8619 register_blank_tiles();
8620 register_used_tiles();
8621
8622 return 1;
8623
8624 }
8625
8626 int32_t readtilefile_to_location(PACKFILE *f, int32_t start, int32_t skip)
8627 {
8628 dword section_version=0;
8629 dword section_cversion=0;
8630 int32_t zversion = 0;
8631 int32_t zbuild = 0;
8632
8633 if(!p_igetl(&zversion,f))
8634 {
8635 return 0;
8636 }
8637 if(!p_igetl(&zbuild,f))
8638 {
8639 return 0;
8640 }
8641 if(!p_igetw(&section_version,f))
8642 {
8643 return 0;
8644 }
8645 if(!p_igetw(&section_cversion,f))
8646 {
8647 return 0;
8648 }
8649 al_trace("readoneweapon section_version: %d\n", section_version);
8650 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8651
8652 if ( zversion > ZELDA_VERSION )
8653 {
8654 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8655 return 0;
8656 }
8657
8658 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8659 {
8660 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8661 return 0;
8662
8663 }
8664 else
8665 {
8666 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8667 }
8668
8669 int32_t index = 0;
8670 int32_t count = 0;
8671
8672 //tile id
8673 if(!p_igetl(&index,f))
8674 {
8675 return 0;
8676 }
8677 al_trace("Reading tile: index(%d)\n", index);
8678
8679 //tile count
8680 if(!p_igetl(&count,f))
8681 {
8682 return 0;
8683 }
8684 al_trace("Reading tile: count(%d)\n", count);
8685
8686
8687 for ( int32_t tilect = 0; tilect < count; tilect++ )
8688 {
8689 byte *temp_tile = new byte[tilesize(tf32Bit)];
8690 byte format=tf4Bit;
8691 memset(temp_tile, 0, tilesize(tf32Bit));
8692 if(!p_getc(&format,f))
8693 {
8694 delete[] temp_tile;
8695 return 0;
8696 }
8697
8698
8699 if(!pfread(temp_tile,tilesize(format),f))
8700 {
8701 delete[] temp_tile;
8702 return 0;
8703 }
8704
8705 reset_tile(newtilebuf, start+(tilect), format);
8706 if ( skip )
8707 {
8708 if ( (start+(tilect)) < skip )
8709 {
8710 delete[] temp_tile;
8711 continue;
8712 }
8713
8714 }
8715 if ( start+(tilect) < NEWMAXTILES )
8716 {
8717 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8718 }
8719 delete[] temp_tile;
8720
8721 }
8722
8723
8724 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8725
8726 register_blank_tiles();
8727 register_used_tiles();
8728
8729 return 1;
8730
8731 }
8732
8733
8734 int32_t readtilefile_to_location(PACKFILE *f, int32_t start)
8735 {
8736 dword section_version=0;
8737 dword section_cversion=0;
8738 int32_t zversion = 0;
8739 int32_t zbuild = 0;
8740
8741 if(!p_igetl(&zversion,f))
8742 {
8743 return 0;
8744 }
8745 if(!p_igetl(&zbuild,f))
8746 {
8747 return 0;
8748 }
8749 if(!p_igetw(&section_version,f))
8750 {
8751 return 0;
8752 }
8753 if(!p_igetw(&section_cversion,f))
8754 {
8755 return 0;
8756 }
8757 al_trace("readoneweapon section_version: %d\n", section_version);
8758 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8759
8760 if ( zversion > ZELDA_VERSION )
8761 {
8762 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8763 return 0;
8764 }
8765
8766 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8767 {
8768 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8769 return 0;
8770
8771 }
8772 else
8773 {
8774 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8775 }
8776
8777 int32_t index = 0;
8778 int32_t count = 0;
8779
8780 //tile id
8781 if(!p_igetl(&index,f))
8782 {
8783 return 0;
8784 }
8785 al_trace("Reading tile: index(%d)\n", index);
8786
8787 //tile count
8788 if(!p_igetl(&count,f))
8789 {
8790 return 0;
8791 }
8792 al_trace("Reading tile: count(%d)\n", count);
8793
8794
8795
8796
8797 for ( int32_t tilect = 0; tilect < count; tilect++ )
8798 {
8799 byte *temp_tile = new byte[tilesize(tf32Bit)];
8800 byte format=tf4Bit;
8801 memset(temp_tile, 0, tilesize(tf32Bit));
8802
8803 if(!p_getc(&format,f))
8804 {
8805 delete[] temp_tile;
8806 return 0;
8807 }
8808
8809
8810 if(!pfread(temp_tile,tilesize(format),f))
8811 {
8812 delete[] temp_tile;
8813 return 0;
8814 }
8815
8816 reset_tile(newtilebuf, start+(tilect), format);
8817 if ( start+(tilect) < NEWMAXTILES )
8818 {
8819 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8820 }
8821 delete[] temp_tile;
8822 }
8823
8824
8825 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8826
8827 register_blank_tiles();
8828 register_used_tiles();
8829
8830 return 1;
8831
8832 }
8833 int32_t writetilefile(PACKFILE *f, int32_t index, int32_t count)
8834 {
8835 dword section_version=V_TILES;
8836 dword section_cversion=CV_TILES;
8837 int32_t zversion = ZELDA_VERSION;
8838 int32_t zbuild = VERSION_BUILD;
8839
8840 if(!p_iputl(zversion,f))
8841 {
8842 return 0;
8843 }
8844 if(!p_iputl(zbuild,f))
8845 {
8846 return 0;
8847 }
8848 if(!p_iputw(section_version,f))
8849 {
8850 return 0;
8851 }
8852
8853 if(!p_iputw(section_cversion,f))
8854 {
8855 return 0;
8856 }
8857
8858 //start tile id
8859 if(!p_iputl(index,f))
8860 {
8861 return 0;
8862 }
8863
8864 //count
8865 if(!p_iputl(count,f))
8866 {
8867 return 0;
8868 }
8869
8870 for ( int32_t tilect = 0; tilect < count; tilect++ )
8871 {
8872 //al_trace("Tile id: %d\n",index+(tilect));
8873 if(!p_putc(newtilebuf[index+(tilect)].format,f))
8874 {
8875 return 0;
8876 }
8877 //al_trace("Tile format: %d\n", newtilebuf[index+(tilect)].format);
8878 if(!pfwrite(newtilebuf[index+(tilect)].data,tilesize(newtilebuf[index+(tilect)].format),f))
8879 {
8880 return 0;
8881 }
8882 }
8883
8884 return 1;
8885
8886 }
8887
8888 static int32_t _selected_tile=-1, _selected_tcset=-1;
8889 int32_t select_tile(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
8890 {
8891 popup_zqdialog_start();
8892 reset_combo_animations();
8893 reset_combo_animations2();
8894 bound(tile,0,NEWMAXTILES-1);
8895 ex=exnow;
8896 int32_t done=0;
8897 int32_t oflip=flip;
8898 int32_t otile=tile;
8899 int32_t ocs=cs;
8900 int32_t first=(tile/TILES_PER_PAGE)*TILES_PER_PAGE; //first tile on the current page
8901 int32_t copy=-1;
8902 int32_t tile2=tile,copycnt=0;
8903 int32_t tile_clicked=-1;
8904 bool rect_sel=true;
8905 bound(first,0,(TILES_PER_PAGE*TILE_PAGES)-1);
8906 position_mouse_z(0);
8907
8908 go();
8909
8910 register_used_tiles();
8911 int32_t w = 640;
8912 int32_t h = 480;
8913 int32_t window_xofs=(zq_screen_w-w-12)>>1;
8914 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
8915 int32_t screen_xofs=window_xofs+6;
8916 int32_t screen_yofs=window_yofs+25;
8917 int32_t panel_yofs=3;
8918 int32_t mul = 2;
8919 FONT *tfont = get_zc_font(font_lfont_l);
8920
8921 draw_tile_list_window();
8922 int32_t f=0;
8923 draw_tiles(first,cs,f);
8924
8925 if(type==0)
8926 {
8927 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
8928 }
8929 else
8930 {
8931 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
8932 }
8933
8934 go_tiles();
8935
8936 while(gui_mouse_b())
8937 {
8938 /* do nothing */
8939 rest(1);
8940 }
8941
8942 bool bdown=false;
8943
8944 #define FOREACH_START(_t) \
8945 { \
8946 int32_t _first, _last; \
8947 if(is_rect) \
8948 { \
8949 _first=top*TILES_PER_ROW+left; \
8950 _last=_first+rows*TILES_PER_ROW|+columns-1; \
8951 } \
8952 else \
8953 { \
8954 _first=zc_min(tile, tile2); \
8955 _last=zc_max(tile, tile2); \
8956 } \
8957 for(int32_t _t=_first; _t<=_last; _t++) \
8958 { \
8959 if(is_rect) \
8960 { \
8961 int32_t row=TILEROW(_t); \
8962 if(row<top || row>=top+rows) \
8963 continue; \
8964 int32_t col=TILECOL(_t); \
8965 if(col<left || col>=left+columns) \
8966 continue; \
8967 } \
8968
8969 #define FOREACH_END\
8970 } \
8971 }
8972
8973 bool did_snap = false;
8974 int otl = tile, otl2 = tile2;
8975 do
8976 {
8977 HANDLE_CLOSE_ZQDLG();
8978 if(exiting_program) break;
8979 rest(4);
8980 int32_t top=TILEROW(zc_min(tile, tile2));
8981 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
8982 int32_t rows=TILEROW(zc_max(tile, tile2))-top+1;
8983 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
8984 bool is_rect=(rows==1)||(columns==TILES_PER_ROW)||rect_sel;
8985 bool redraw=false;
8986
8987 if(mouse_z!=0)
8988 {
8989 sel_tile(tile,tile2,first,type,((mouse_z/abs(mouse_z))*(-1)*TILES_PER_PAGE));
8990 position_mouse_z(0);
8991 redraw=true;
8992 }
8993
8994 if(keypressed())
8995 {
8996 switch(readkey()>>8)
8997 {
8998 case KEY_ENTER_PAD:
8999 case KEY_ENTER:
9000 done=2;
9001 break;
9002
9003 case KEY_ESC:
9004 done=1;
9005 break;
9006
9007 case KEY_F1:
9008 onHelp();
9009 break;
9010
9011 case KEY_EQUALS:
9012 case KEY_PLUS_PAD:
9013 {
9014 if(CHECK_CTRL_CMD ||
9015 key[KEY_ALT] || key[KEY_ALTGR])
9016 {
9017 FOREACH_START(t)
9018 if(key[KEY_ALT] || key[KEY_ALTGR])
9019 shift_tile_colors(t, 16, false);
9020 else
9021 shift_tile_colors(t, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9022 FOREACH_END
9023
9024 register_blank_tiles();
9025 }
9026 else if(edit_cs)
9027 cs = (cs<13) ? cs+1:0;
9028
9029 redraw=true;
9030 break;
9031 }
9032
9033 case KEY_Z:
9034 case KEY_F12:
9035 {
9036 if(!did_snap)
9037 {
9038 //Export tile page as screenshot
9039 PALETTE temppal;
9040 get_palette(temppal);
9041 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
9042 draw_tiles(tempbmp,first,cs,f,false,true);
9043 save_bitmap(getSnapName(), tempbmp, RAMpal);
9044 destroy_bitmap(tempbmp);
9045
9046 redraw = true;
9047 did_snap = true;
9048 }
9049 break;
9050 }
9051
9052 case KEY_S:
9053 {
9054 if(!getname("Save ZTILE(.ztile)", "ztile", NULL,datapath,false))
9055 break;
9056 PACKFILE *f=pack_fopen_password(temppath,F_WRITE, "");
9057 if(!f) break;
9058 al_trace("Saving tile: %d\n", tile);
9059 writetilefile(f,tile,1);
9060 pack_fclose(f);
9061 break;
9062 }
9063 case KEY_L:
9064 {
9065 if(!getname("Load ZTILE(.ztile)", "ztile", NULL,datapath,false))
9066 break;
9067 PACKFILE *f=pack_fopen_password(temppath,F_READ, "");
9068 if(!f) break;
9069 al_trace("Saving tile: %d\n", tile);
9070 if (!readtilefile(f))
9071 {
9072 al_trace("Could not read from .ztile packfile %s\n", temppath);
9073 jwin_alert("ZTILE File: Error","Could not load the specified Tile.",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9074 }
9075 else
9076 {
9077 jwin_alert("ZTILE File: Success!","Loaded the source tiles to your tile sheets!",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9078 }
9079
9080 pack_fclose(f);
9081 //register_blank_tiles();
9082 //register_used_tiles();
9083 redraw=true;
9084 break;
9085 }
9086 case KEY_MINUS:
9087 case KEY_MINUS_PAD:
9088 {
9089 if(CHECK_CTRL_CMD ||
9090 key[KEY_ALT] || key[KEY_ALTGR])
9091 {
9092 FOREACH_START(t)
9093 if(key[KEY_ALT] || key[KEY_ALTGR])
9094 shift_tile_colors(t, -16, false);
9095 else
9096 shift_tile_colors(t, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9097 FOREACH_END
9098
9099 register_blank_tiles();
9100 }
9101 else if(edit_cs)
9102 cs = (cs>0) ? cs-1:13;
9103
9104 redraw=true;
9105 break;
9106 }
9107
9108 case KEY_UP:
9109 {
9110 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9111 {
9112 case 3: //ALT and CTRL
9113 case 2: //ALT
9114 if(is_rect)
9115 {
9116 saved=false;
9117 go_slide_tiles(columns, rows, top, left);
9118 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9119 bool same = true;
9120
9121 for(int32_t d=0; d<columns; d++)
9122 {
9123 for(int32_t s=0; s<rows; s++)
9124 {
9125 int32_t t=((top+s)*TILES_PER_ROW)+left+d;
9126
9127 if(newtilebuf[t].format!=bitcheck) same = false;
9128 }
9129 }
9130
9131 if(!same) break;
9132
9133 // This used to do something. Too lazy to remove.
9134 // Can probably remove the above "same" check too.
9135 bitcheck = 2;
9136
9137 for(int32_t c=0; c<columns; c++)
9138 {
9139 for(int32_t r=0; r<rows; r++)
9140 {
9141 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9142 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(8*bitcheck));
9143 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data);
9144
9145 for(int32_t pixelrow=0; pixelrow<16*bitcheck; pixelrow++)
9146 {
9147 if(pixelrow==15*bitcheck)
9148 {
9149 int32_t srctile=temptile+TILES_PER_ROW;
9150 if(srctile>=NEWMAXTILES)
9151 srctile-=rows*TILES_PER_ROW;
9152 src_pixelrow=(qword*)(newtilebuf[srctile].data);
9153 }
9154
9155 *dest_pixelrow=*src_pixelrow;
9156 dest_pixelrow++;
9157 src_pixelrow++;
9158 }
9159 }
9160
9161 qword *dest_pixelrow=(qword*)(newtilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9162
9163 for(int32_t b=0; b<bitcheck; b++,dest_pixelrow++)
9164 {
9165 if((CHECK_CTRL_CMD))
9166 {
9167 *dest_pixelrow=0;
9168 }
9169 else
9170 {
9171 qword *src_pixelrow=(qword*)(newundotilebuf[(top*TILES_PER_ROW)+left+c].data+(8*b));
9172 *dest_pixelrow=*src_pixelrow;
9173 }
9174 }
9175 }
9176 }
9177
9178 register_blank_tiles();
9179 redraw=true;
9180 break;
9181
9182 case 1: //CTRL
9183 case 0: //None
9184 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(tile_page_row(tile)*TILES_PER_ROW):-TILES_PER_ROW);
9185 redraw=true;
9186
9187 default: //Others
9188 break;
9189 }
9190 }
9191 break;
9192
9193 case KEY_DOWN:
9194 {
9195 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9196 {
9197 case 3: //ALT and CTRL
9198 case 2: //ALT
9199 if(is_rect)
9200 {
9201 saved=false;
9202 go_slide_tiles(columns, rows, top, left);
9203 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9204 bool same = true;
9205
9206 for(int32_t c=0; c<columns; c++)
9207 {
9208 for(int32_t r=0; r<rows; r++)
9209 {
9210 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9211
9212 if(newtilebuf[t].format!=bitcheck) same = false;
9213 }
9214 }
9215
9216 if(!same) break;
9217
9218 // This used to do something. Too lazy to remove.
9219 // Can probably remove the above "same" check too.
9220 bitcheck = 2;
9221
9222 for(int32_t c=0; c<columns; c++)
9223 {
9224 for(int32_t r=rows-1; r>=0; r--)
9225 {
9226 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9227 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(112*bitcheck)+(8*(bitcheck-1)));
9228 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data+(120*bitcheck)+(8*(bitcheck-1)));
9229
9230 for(int32_t pixelrow=(8<<bitcheck)-1; pixelrow>=0; pixelrow--)
9231 {
9232 if(pixelrow<bitcheck)
9233 {
9234 int32_t srctile=temptile-TILES_PER_ROW;
9235 if(srctile<0)
9236 srctile+=rows*TILES_PER_ROW;
9237 qword *tempsrc=(qword*)(newtilebuf[srctile].data+(120*bitcheck)+(8*pixelrow));
9238 *dest_pixelrow=*tempsrc;
9239 //*dest_pixelrow=0;
9240 }
9241 else
9242 {
9243 *dest_pixelrow=*src_pixelrow;
9244 }
9245
9246 dest_pixelrow--;
9247 src_pixelrow--;
9248 }
9249 }
9250
9251 qword *dest_pixelrow=(qword*)(newtilebuf[(top*TILES_PER_ROW)+left+c].data);
9252 qword *src_pixelrow=(qword*)(newundotilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9253
9254 for(int32_t b=0; b<bitcheck; b++)
9255 {
9256 if((CHECK_CTRL_CMD))
9257 {
9258 *dest_pixelrow=0;
9259 }
9260 else
9261 {
9262 *dest_pixelrow=*src_pixelrow;
9263 }
9264
9265 dest_pixelrow++;
9266 src_pixelrow++;
9267 }
9268 }
9269 }
9270
9271 register_blank_tiles();
9272 redraw=true;
9273 break;
9274
9275 case 1: //CTRL
9276 case 0: //None
9277 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_ROWS_PER_PAGE-1)-tile_page_row(tile))*TILES_PER_ROW:TILES_PER_ROW);
9278 redraw=true;
9279
9280 default: //Others
9281 break;
9282 }
9283 }
9284 break;
9285
9286 case KEY_LEFT:
9287 {
9288 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9289 {
9290 case 3: //ALT and CTRL
9291 case 2: //ALT
9292 if(is_rect)
9293 {
9294 saved=false;
9295 go_slide_tiles(columns, rows, top, left);
9296 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9297 bool same = true;
9298
9299 for(int32_t c=0; c<columns; c++)
9300 {
9301 for(int32_t r=0; r<rows; r++)
9302 {
9303 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9304
9305 if(newtilebuf[t].format!=bitcheck) same = false;
9306 }
9307 }
9308
9309 if(!same) break;
9310
9311 // This used to do something. Too lazy to remove.
9312 // Can probably remove the above "same" check too.
9313 bitcheck = 2;
9314
9315 for(int32_t r=0; r<rows; r++)
9316 {
9317 for(int32_t c=0; c<columns; c++)
9318 {
9319 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9320 byte *dest_pixelrow=(newtilebuf[temptile].data);
9321
9322 for(int32_t pixelrow=0; pixelrow<16; pixelrow++)
9323 {
9324 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9325 {
9326 *dest_pixelrow=*(dest_pixelrow+1);
9327 dest_pixelrow++;
9328 }
9329
9330 if(c==columns-1)
9331 {
9332 if(!(CHECK_CTRL_CMD))
9333 {
9334 byte *tempsrc=(newundotilebuf[((top+r)*TILES_PER_ROW)+left].data+(pixelrow*8*bitcheck));
9335 *dest_pixelrow=*tempsrc;
9336 }
9337 }
9338 else
9339
9340 {
9341 byte *tempsrc=(newtilebuf[temptile+1].data+(pixelrow*8*bitcheck));
9342 *dest_pixelrow=*tempsrc;
9343 }
9344
9345 dest_pixelrow++;
9346 }
9347 }
9348 }
9349
9350 register_blank_tiles();
9351 redraw=true;
9352 }
9353
9354 break;
9355
9356 case 1: //CTRL
9357 case 0: //None
9358 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile%TILES_PER_ROW):-1);
9359 redraw=true;
9360
9361 default: //Others
9362 break;
9363 }
9364 }
9365 break;
9366
9367 case KEY_RIGHT:
9368 {
9369 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9370 {
9371 case 3: //ALT and CTRL
9372 case 2: //ALT
9373 if(is_rect)
9374 {
9375 saved=false;
9376 go_slide_tiles(columns, rows, top, left);
9377 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9378 bool same = true;
9379
9380 for(int32_t c=0; c<columns; c++)
9381 {
9382 for(int32_t r=0; r<rows; r++)
9383 {
9384 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9385
9386 if(newtilebuf[t].format!=bitcheck) same = false;
9387 }
9388 }
9389
9390 if(!same) break;
9391
9392 // This used to do something. Too lazy to remove.
9393 // Can probably remove the above "same" check too.
9394 bitcheck = 2;
9395
9396 for(int32_t r=0; r<rows; r++)
9397 {
9398 for(int32_t c=columns-1; c>=0; c--)
9399 {
9400 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9401 byte *dest_pixelrow=(newtilebuf[temptile].data)+(128*bitcheck)-1;
9402
9403 for(int32_t pixelrow=15; pixelrow>=0; pixelrow--)
9404 {
9405 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9406 {
9407 *dest_pixelrow=*(dest_pixelrow-1);
9408 dest_pixelrow--;
9409 }
9410
9411 if(c==0)
9412 {
9413 if(!(CHECK_CTRL_CMD))
9414 {
9415 byte *tempsrc=(newundotilebuf[(((top+r)*TILES_PER_ROW)+left+columns-1)].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9416 *dest_pixelrow=*tempsrc;
9417 }
9418 }
9419 else
9420 {
9421 byte *tempsrc=(newtilebuf[temptile-1].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9422 *dest_pixelrow=*tempsrc;
9423 }
9424
9425 dest_pixelrow--;
9426 }
9427 }
9428 }
9429
9430 register_blank_tiles();
9431 redraw=true;
9432 }
9433
9434 break;
9435
9436 case 1: //CTRL
9437 case 0: //None
9438 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILES_PER_ROW)-(tile%TILES_PER_ROW)-1:1);
9439 redraw=true;
9440
9441 default: //Others
9442 break;
9443 }
9444 }
9445 break;
9446
9447 case KEY_PGUP:
9448 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(TILEROW(tile)*TILES_PER_ROW):-TILES_PER_PAGE);
9449 redraw=true;
9450 break;
9451
9452 case KEY_PGDN:
9453 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_PAGES*TILE_ROWS_PER_PAGE)-TILEROW(tile)-1)*TILES_PER_ROW:TILES_PER_PAGE);
9454 redraw=true;
9455 break;
9456
9457 case KEY_HOME:
9458 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile):-(tile%TILES_PER_PAGE));
9459 redraw=true;
9460 break;
9461
9462 case KEY_END:
9463 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILE_PAGES)*(TILES_PER_PAGE)-tile-1:(TILES_PER_PAGE)-(tile%TILES_PER_PAGE)-1);
9464 redraw=true;
9465 break;
9466
9467 case KEY_P:
9468 {
9469 int32_t whatPage = gettilepagenumber("Goto Page", (PreFillTileEditorPage?(first/TILES_PER_PAGE):0));
9470
9471 if(whatPage >= 0)
9472 sel_tile(tile,tile2,first,type,((whatPage-TILEPAGE(tile))*TILE_ROWS_PER_PAGE)*TILES_PER_ROW);
9473
9474 break;
9475 }
9476
9477 case KEY_O:
9478 if(type==0 && copy>=0)
9479 {
9480 go_tiles();
9481
9482 if(key[KEY_LSHIFT] ||key[KEY_RSHIFT])
9483 {
9484 mass_overlay_tile(zc_min(tile,tile2),zc_max(tile,tile2),copy,cs,(CHECK_CTRL_CMD), rect_sel);
9485 saved=false;
9486 }
9487 else
9488 {
9489 saved = !overlay_tiles(tile,tile2,copy,copycnt,rect_sel,false,cs,(CHECK_CTRL_CMD));
9490 //overlay_tile(newtilebuf,tile,copy,cs,(CHECK_CTRL_CMD));
9491 }
9492
9493 saved=false;
9494 redraw=true;
9495 }
9496
9497 break;
9498
9499 case KEY_E:
9500 if(type==0)
9501 {
9502 edit_tile(tile,flip,cs);
9503 draw_tile_list_window();
9504 redraw=true;
9505 }
9506
9507 break;
9508
9509 case KEY_G:
9510 if(type==0)
9511 {
9512 grab_tile(tile,cs);
9513 draw_tile_list_window();
9514 redraw=true;
9515 }
9516
9517 break;
9518
9519 case KEY_C:
9520 copy=zc_min(tile,tile2);
9521 copycnt=abs(tile-tile2)+1;
9522 redraw=true;
9523 break;
9524
9525 case KEY_X:
9526 if(type==2)
9527 {
9528 ex=(ex+1)%3;
9529 }
9530
9531 break;
9532
9533 //usetiles=true;
9534 case KEY_R:
9535 if(type==2)
9536 break;
9537 if(type==1)
9538 {
9539 flip = rotate_value(flip);
9540 redraw=true;
9541 break;
9542 }
9543
9544 go_tiles();
9545
9546 if(CHECK_CTRL_CMD)
9547 {
9548 bool go=false;
9549 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
9550 go=true;
9551 else if(massRecolorSetup(cs))
9552 go=true;
9553
9554 if(go)
9555 {
9556 FOREACH_START(t)
9557 massRecolorApply(t);
9558 FOREACH_END
9559
9560 register_blank_tiles();
9561 }
9562 }
9563 else
9564 {
9565 FOREACH_START(t)
9566 rotate_tile(t,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
9567 FOREACH_END
9568 }
9569
9570 redraw=true;
9571 saved=false;
9572 break;
9573
9574 case KEY_SPACE:
9575 rect_sel=!rect_sel;
9576 copy=-1;
9577 redraw=true;
9578 break;
9579
9580 // case KEY_N: go_tiles(); normalize(tile,tile2,flip); flip=0; redraw=true; saved=false; usetiles=true; break;
9581 case KEY_H:
9582 flip^=1;
9583 go_tiles();
9584
9585 if(type==0)
9586 {
9587 normalize(tile,tile2,rect_sel,flip);
9588 flip=0;
9589 }
9590
9591 redraw=true;
9592 break;
9593
9594
9595 case KEY_V:
9596 if(copy==-1)
9597 {
9598 if(type!=2)
9599 {
9600 flip^=2;
9601 go_tiles();
9602
9603 if(type==0)
9604 {
9605 normalize(tile,tile2,rect_sel,flip);
9606 flip=0;
9607 }
9608 }
9609 }
9610 else
9611 {
9612 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9613 go_tiles();
9614 saved = !copy_tiles(tile,tile2,copy,copycnt,rect_sel,false);
9615 }
9616
9617 redraw=true;
9618 break;
9619
9620 case KEY_F:
9621 if(copy==-1)
9622 {
9623 break;
9624 }
9625 else
9626 {
9627 go_tiles();
9628 {
9629 saved = !copy_tiles_floodfill(tile,tile2,copy,copycnt,rect_sel,false);
9630 }
9631 }
9632
9633 redraw=true;
9634 break;
9635
9636 case KEY_DEL:
9637 if(type==0 && (key[KEY_LSHIFT]||key[KEY_RSHIFT]))
9638 {
9639 bool warn = (rect_sel
9640 && ((tile/20)!=(tile2/20))
9641 && !(tile%20==0&&tile2%20==19));
9642 int32_t z=zc_min(tile,tile2);
9643 int32_t count = abs(tile-tile2) + 1;
9644 tile=z;
9645 tile2=NEWMAXTILES;
9646 copy = tile + count;
9647 copycnt = NEWMAXTILES-copy;
9648 char buf[64];
9649
9650 if(count>1)
9651 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9652 else
9653 sprintf(buf,"Remove tile %d?",tile);
9654
9655 AlertDialog("Remove Tiles", std::string(buf)
9656 +"\nThis will offset the tiles that follow!"
9657 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9658 [&](bool ret,bool)
9659 {
9660 if(ret)
9661 {
9662 go_tiles();
9663 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9664 {
9665 redraw=true;
9666 saved=false;
9667 }
9668 }
9669 }).show();
9670 }
9671 delete_tiles(tile,tile2,rect_sel);
9672 redraw=true;
9673 break;
9674
9675 case KEY_U:
9676 {
9677 if(CHECK_CTRL_CMD)
9678 {
9679 //Only toggle the first 2 bits!
9680 show_only_unused_tiles = (show_only_unused_tiles&~3) | (((show_only_unused_tiles&3)+1)%4);
9681 }
9682 else
9683 {
9684 comeback_tiles();
9685 }
9686
9687 redraw=true;
9688 }
9689 break;
9690
9691 case KEY_8:
9692 case KEY_8_PAD:
9693 hide_8bit_marker();
9694 break;
9695
9696 case KEY_I: //insert tiles
9697 if(type==0)
9698 {
9699 bool warn = (rect_sel
9700 && ((tile/20)!=(tile2/20))
9701 && !(tile%20==0&&tile2%20==19));
9702 int32_t z=zc_min(tile,tile2);
9703 int32_t count = abs(tile-tile2) + 1;
9704 tile=z;
9705 tile2=NEWMAXTILES;
9706 copy = tile + count;
9707 copycnt = NEWMAXTILES-copy;
9708
9709 if(key[KEY_LSHIFT]||key[KEY_RSHIFT]) //Remove
9710 {
9711 char buf[64];
9712
9713 if(count>1)
9714 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9715 else
9716 sprintf(buf,"Remove tile %d?",tile);
9717
9718 AlertDialog("Remove Tiles", std::string(buf)
9719 +"\nThis will offset the tiles that follow!"
9720 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9721 [&](bool ret,bool)
9722 {
9723 if(ret)
9724 {
9725 go_tiles();
9726 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9727 {
9728 redraw=true;
9729 saved=false;
9730 }
9731 }
9732 }).show();
9733 }
9734 else
9735 {
9736 char buf[64];
9737
9738 if(count>1)
9739 sprintf(buf,"Insert %d blank tiles?",count);
9740 else
9741 sprintf(buf,"Insert a blank tile?");
9742
9743 AlertDialog("Insert Tiles", std::string(buf)
9744 +"\nThis will offset the tiles that follow!"
9745 +(warn?"\nInserting tiles ignores rectangular selections!":""),
9746 [&](bool ret,bool)
9747 {
9748 if(ret)
9749 {
9750 go_tiles();
9751 if(copy_tiles(copy,tile2,tile,copycnt,false,true))
9752 {
9753 redraw=true;
9754 saved=false;
9755 }
9756 }
9757 }).show();
9758 }
9759
9760 copy=-1;
9761 tile2=tile=z;
9762 }
9763 break;
9764 case KEY_M:
9765 if(type==0)
9766 {
9767 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
9768 {
9769 go_tiles();
9770 if(copy_tiles(tile,tile2,copy,copycnt,rect_sel,true))
9771 saved=false;
9772 }
9773 else if(copy==-1)
9774 {
9775 // I don't know what this was supposed to be doing before.
9776 // It didn't work in anything like a sensible way.
9777 if(rect_sel)
9778 {
9779 make_combos_rect(top, left, rows, columns, cs);
9780 }
9781 else
9782 {
9783 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
9784 }
9785 }
9786
9787 redraw=true;
9788 }
9789 break;
9790
9791 case KEY_D:
9792 {
9793 int32_t frames=1;
9794 char buf[80];
9795 sprintf(buf, "%d", frames);
9796 create_relational_tiles_dlg[0].dp2=get_zc_font(font_lfont);
9797 create_relational_tiles_dlg[2].dp=buf;
9798
9799 large_dialog(create_relational_tiles_dlg);
9800
9801 int32_t ret=do_zqdialog(create_relational_tiles_dlg,2);
9802
9803 if(ret==5)
9804 {
9805 frames=zc_max(atoi(buf),1);
9806 bool same = true;
9807 int32_t bitcheck=newtilebuf[tile].format;
9808
9809 for(int32_t t=1; t<frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); ++t)
9810 {
9811 if(newtilebuf[tile+t].format!=bitcheck) same = false;
9812 }
9813
9814 if(!same)
9815 {
9816 jwin_alert("Error","The source tiles are not","in the same format.",NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9817 break;
9818 }
9819
9820 if(tile+(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96))>NEWMAXTILES)
9821 {
9822 jwin_alert("Error","Too many tiles will be created",NULL,NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9823 break;
9824 }
9825
9826 for(int32_t i=frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); i<(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96)); ++i)
9827 {
9828 reset_tile(newtilebuf, tile+i, bitcheck);
9829 }
9830
9831 if(create_relational_tiles_dlg[3].flags&D_SELECTED)
9832 {
9833 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9834 {
9835 for(int32_t j=0; j<frames; ++j)
9836 {
9837 merge_tiles(tile+(i*frames)+j, (tile+(relational_template[i][0]*frames)+j)<<2, ((tile+(relational_template[i][1]*frames)+j)<<2)+1, ((tile+(relational_template[i][2]*frames)+j)<<2)+2, ((tile+(relational_template[i][3]*frames)+j)<<2)+3);
9838 }
9839 }
9840 }
9841 else
9842 {
9843 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9844 {
9845 for(int32_t j=0; j<frames; ++j)
9846 {
9847 merge_tiles(tile+(i*frames)+j, (tile+(dungeon_carving_template[i][0]*frames)+j)<<2, ((tile+(dungeon_carving_template[i][1]*frames)+j)<<2)+1, ((tile+(dungeon_carving_template[i][2]*frames)+j)<<2)+2, ((tile+(dungeon_carving_template[i][3]*frames)+j)<<2)+3);
9848 }
9849 }
9850 }
9851 }
9852 register_blank_tiles();
9853 register_used_tiles();
9854 redraw=true;
9855 saved=false;
9856 break;
9857 }
9858
9859 case KEY_B:
9860 {
9861 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9862 bool control=(CHECK_CTRL_CMD);
9863 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9864
9865 do_convert_tile(tile, tile2, cs, rect_sel, control, shift, alt);
9866 register_blank_tiles();
9867 }
9868 break;
9869 }
9870
9871 clear_keybuf();
9872 }
9873
9874 if(!(key[KEY_Z] || key[KEY_F12]))
9875 did_snap = false;
9876
9877 if(gui_mouse_b()&1)
9878 {
9879 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
9880 {
9881 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
9882 {
9883 done=1;
9884 }
9885 }
9886
9887 int32_t x=gui_mouse_x()-screen_xofs;
9888 int32_t y=gui_mouse_y()-screen_yofs;
9889
9890 if(y>=0 && y<208*mul)
9891 {
9892 x=zc_min(zc_max(x,0),(320*mul)-1);
9893 int32_t t = (y>>(5))*TILES_PER_ROW + (x>>(5)) + first;
9894
9895 if(type==0 && (key[KEY_LSHIFT] || key[KEY_RSHIFT]))
9896 {
9897 tile2=t;
9898 }
9899 else
9900 {
9901 tile=tile2=t;
9902 }
9903
9904 if(tile_clicked!=t)
9905 {
9906 dclick_status=DCLICK_NOT;
9907 }
9908 else if(dclick_status == DCLICK_AGAIN)
9909 {
9910 while(gui_mouse_b())
9911 {
9912 /* do nothing */
9913 rest(1);
9914 }
9915
9916 if(((y>>(5))*TILES_PER_ROW + (x>>(5)) + first)!=t)
9917 {
9918 dclick_status=DCLICK_NOT;
9919 }
9920 else
9921 {
9922 if(type==0)
9923 {
9924 edit_tile(tile,flip,cs);
9925 draw_tile_list_window();
9926 redraw=true;
9927 }
9928 else
9929 {
9930 done=2;
9931 }
9932 }
9933 }
9934
9935 tile_clicked=t;
9936 }
9937 else if(x>300*mul && !bdown)
9938 {
9939 if(y<224*mul && first>0)
9940 {
9941 first-=TILES_PER_PAGE;
9942 redraw=true;
9943 }
9944
9945 if(y>=224*mul && first<TILES_PER_PAGE*(TILE_PAGES-1))
9946 {
9947 first+=TILES_PER_PAGE;
9948 redraw=true;
9949 }
9950
9951 bdown=true;
9952 }
9953
9954 if(type==1||type==2)
9955 {
9956 if(!bdown && isinRect(x,y,8*mul,216*mul+panel_yofs,23*mul,231*mul+panel_yofs))
9957 done=1;
9958
9959 if(!bdown && isinRect(x,y,148*mul,216*mul+panel_yofs,163*mul,231*mul+panel_yofs))
9960 done=2;
9961 }
9962 else if(!bdown && isinRect(x,y,127*mul,216*mul+panel_yofs,(127+15)*mul,(216+15)*mul+panel_yofs))
9963 {
9964 rect_sel=!rect_sel;
9965 copy=-1;
9966 redraw=true;
9967 }
9968 else if(!bdown && isinRect(x,y,150*mul,213*mul+panel_yofs,(150+28)*mul,(213+21)*mul+panel_yofs))
9969 {
9970 FONT *tf = font;
9971 font = tfont;
9972
9973 if(do_text_button(150*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Grab"))
9974 {
9975 font = tf;
9976 grab_tile(tile,cs);
9977 draw_tile_list_window();
9978 position_mouse_z(0);
9979 redraw=true;
9980 }
9981
9982 font = tf;
9983 }
9984 else if(!bdown && isinRect(x,y,(150+28)*mul,213*mul+panel_yofs,(150+28*2)*mul,(213+21)*mul+panel_yofs+21))
9985 {
9986 FONT *tf = font;
9987 font = tfont;
9988
9989 if(do_text_button((150+28)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Edit"))
9990 {
9991 font = tf;
9992 edit_tile(tile,flip,cs);
9993 draw_tile_list_window();
9994 redraw=true;
9995 }
9996
9997 font = tf;
9998 }
9999 else if(!bdown && isinRect(x,y,(150+28*2)*mul,213*mul+panel_yofs,(150+28*3)*mul,(213+21)*mul+panel_yofs))
10000 {
10001 FONT *tf = font;
10002 font = tfont;
10003
10004 if(do_text_button((150+28*2)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Export"))
10005 {
10006 strcpy(datapath, "tileset.png");
10007 if(getname("Export Tile Page (.png)","png",NULL,datapath,true))
10008 {
10009 PALETTE temppal;
10010 get_palette(temppal);
10011 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
10012 draw_tiles(tempbmp,first,cs,f,false,true);
10013 save_bitmap(temppath, tempbmp, RAMpal);
10014 destroy_bitmap(tempbmp);
10015 }
10016 }
10017
10018 font = tf;
10019 }
10020 else if(!bdown && isinRect(x,y,(150+28*3)*mul,213*mul+panel_yofs,(150+28*4)*mul,(213+21)*mul+panel_yofs))
10021 {
10022 FONT *tf = font;
10023 font = tfont;
10024
10025 if(do_text_button((150+28*3)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Recolor"))
10026 {
10027 if(massRecolorSetup(cs))
10028 {
10029 go_tiles();
10030
10031 FOREACH_START(t)
10032 massRecolorApply(t);
10033 FOREACH_END
10034
10035 register_blank_tiles();
10036 }
10037 }
10038
10039 font = tf;
10040 }
10041 else if(!bdown && isinRect(x,y,(150+28*4)*mul,213*mul+panel_yofs,(150+28*5)*mul,(213+21)*mul+panel_yofs))
10042 {
10043 FONT *tf = font;
10044 font = tfont;
10045
10046 if(do_text_button((150+28*4)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Done"))
10047 {
10048 done=1;
10049 }
10050
10051 font = tf;
10052 }
10053
10054 bdown=true;
10055 }
10056
10057 bool r_click = false;
10058
10059 if(gui_mouse_b()&2 && !bdown && type==0)
10060 {
10061 int32_t x=(gui_mouse_x()-screen_xofs);//&0xFF0;
10062 int32_t y=(gui_mouse_y()-screen_yofs);//&0xF0;
10063
10064 if(y>=0 && y<208*mul)
10065 {
10066 x=zc_min(zc_max(x,0),(320*mul)-1);
10067 int32_t t = ((y)>>(5))*TILES_PER_ROW + ((x)>>(5)) + first;
10068
10069 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
10070 tile=tile2=t;
10071 }
10072
10073 bdown = r_click = true;
10074 f=8;
10075 }
10076
10077 if(gui_mouse_b()==0)
10078 bdown=false;
10079
10080 position_mouse_z(0);
10081
10082 REDRAW:
10083
10084 if((f%8)==0 || InvalidBG == 1)
10085 redraw=true;
10086 if(otl != tile || otl2 != tile2)
10087 {
10088 otl = tile;
10089 otl2 = tile2;
10090 redraw = true;
10091 }
10092
10093 if(redraw)
10094 {
10095 draw_tiles(first,cs,f);
10096 }
10097 if(f&8)
10098 {
10099 if(rect_sel)
10100 {
10101 for(int32_t i=zc_min(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10102 zc_min(TILECOL(tile),TILECOL(tile2));
10103 i<=zc_max(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10104 zc_max(TILECOL(tile),TILECOL(tile2)); i++)
10105 {
10106 if(i>=first && i<first+TILES_PER_PAGE &&
10107 TILECOL(i)>=zc_min(TILECOL(tile),TILECOL(tile2)) &&
10108 TILECOL(i)<=zc_max(TILECOL(tile),TILECOL(tile2)))
10109 {
10110 int32_t x=TILECOL(i)<<(5);
10111 int32_t y=TILEROW(i-first)<<(5);
10112 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10113 }
10114 }
10115 }
10116 else
10117 {
10118 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
10119 {
10120 if(i>=first && i<first+TILES_PER_PAGE)
10121 {
10122 int32_t x=TILECOL(i)<<(5);
10123 int32_t y=TILEROW(i-first)<<(5);
10124 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10125 }
10126 }
10127 }
10128 }
10129
10130 if(type==0)
10131 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
10132 else
10133 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
10134
10135 if(type==2)
10136 {
10137 char cbuf[16];
10138 sprintf(cbuf, "E&xtend: %s",ex==2 ? "32x32" : ex==1 ? "32x16" : "16x16");
10139 gui_textout_ln(screen, get_zc_font(font_lfont_l), (uint8_t *)cbuf, (235*mul)+screen_xofs, (212*mul)+screen_yofs+panel_yofs, jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
10140 }
10141
10142 ++f;
10143
10144 if(r_click)
10145 {
10146 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_USED, HIDE_USED);
10147 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_UNUSED, HIDE_UNUSED);
10148 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_BLANK, HIDE_BLANK);
10149 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_8BIT, HIDE_8BIT_MARKER);
10150 NewMenu rcmenu
10151 {
10152 { "Copy", [&]()
10153 {
10154 copy = zc_min(tile,tile2);
10155 copycnt = abs(tile-tile2)+1;
10156 } },
10157 { "Paste", [&]()
10158 {
10159 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, false);
10160 if(saved) saved = !b;
10161 }, nullopt, copy < 0 },
10162 { "Move", [&]()
10163 {
10164 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, true);
10165 if(saved) saved = !b;
10166 }, nullopt, copy < 0 },
10167 { "Clear", [&]()
10168 {
10169 delete_tiles(tile, tile2, rect_sel);
10170 } },
10171 {},
10172 { "Edit", [&]()
10173 {
10174 edit_tile(tile, flip, cs);
10175 draw_tile_list_window();
10176 } },
10177 { "Grab", [&]()
10178 {
10179 grab_tile(tile, cs);
10180 draw_tile_list_window();
10181 position_mouse_z(0);
10182 } },
10183 { "Scale", [&]()
10184 {
10185 bool b = scale_or_rotate_tiles(tile, tile2, cs, false);
10186 if(saved) saved = !b;
10187 }, nullopt, type != 0 },
10188 { "Angular Rotation", [&]()
10189 {
10190 bool b = scale_or_rotate_tiles(tile, tile2, cs, true);
10191 if(saved) saved = !b;
10192 }, nullopt, type != 0 },
10193 { "Color Depth", [&]()
10194 {
10195 do_convert_tile(tile, tile2, cs, rect_sel,
10196 (newtilebuf[tile].format!=tf4Bit), false, false);
10197 } },
10198 {},
10199 { "Blank?", [&]()
10200 {
10201 show_blank_tile(tile);
10202 } },
10203 {},
10204 { "View ", &select_tile_view_menu },
10205 { "Overlay", [&]()
10206 {
10207 overlay_tile(newtilebuf, tile, copy, cs, 0);
10208 } },
10209 { "H-Flip", [&]()
10210 {
10211 flip ^= 1;
10212 go_tiles();
10213
10214 if(type == 0)
10215 {
10216 normalize(tile, tile2, rect_sel, flip);
10217 flip = 0;
10218 }
10219 } },
10220 { "V-Flip", [&]()
10221 {
10222 flip ^= 2;
10223 go_tiles();
10224
10225 if(type == 0)
10226 {
10227 normalize(tile, tile2, rect_sel, flip);
10228 flip = 0;
10229 }
10230 } },
10231 { "Create Combos", [&]()
10232 {
10233 if(rect_sel)
10234 make_combos_rect(top, left, rows, columns, cs);
10235 else
10236 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
10237 }, nullopt, type != 0 },
10238 { "Insert", [&]()
10239 {
10240 bool warn = (rect_sel
10241 && ((tile/20)!=(tile2/20))
10242 && !(tile%20==0&&tile2%20==19));
10243 int32_t z = zc_min(tile, tile2);
10244 int32_t count = abs(tile-tile2) + 1;
10245 tile = z;
10246 tile2 = NEWMAXTILES;
10247 copy = tile + count;
10248 copycnt = NEWMAXTILES-copy;
10249
10250 string msg;
10251
10252 if(count>1)
10253 msg = fmt::format("Insert {} blank tiles?",count);
10254 else
10255 msg = "Insert a blank tile?";
10256
10257 AlertDialog("Insert Tiles", msg
10258 +"\nThis will offset the tiles that follow!"
10259 +(warn?"\nInserting tiles ignores rectangular selections!":""),
10260 [&](bool ret,bool)
10261 {
10262 if(ret)
10263 {
10264 go_tiles();
10265 if(copy_tiles(copy, tile2, tile, copycnt, false, true))
10266 saved = false;
10267 }
10268 }).show();
10269
10270 copy=-1;
10271 tile2=tile=z;
10272 }, nullopt, type != 0 },
10273 { "Remove", [&]()
10274 {
10275 bool warn = (rect_sel
10276 && ((tile/20)!=(tile2/20))
10277 && !(tile%20==0&&tile2%20==19));
10278 int32_t z = zc_min(tile, tile2);
10279 int32_t count = abs(tile-tile2) + 1;
10280 tile = z;
10281 tile2 = NEWMAXTILES;
10282 copy = tile + count;
10283 copycnt = NEWMAXTILES-copy;
10284
10285 string msg;
10286
10287 if(count>1)
10288 msg = fmt::format("Remove tiles {} - {}?", tile, copy-1);
10289 else
10290 msg = fmt::format("Remove tile {}?", tile);
10291
10292 AlertDialog("Remove Tiles", msg
10293 +"\nThis will offset the tiles that follow!"
10294 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
10295 [&](bool ret,bool)
10296 {
10297 if(ret)
10298 {
10299 go_tiles();
10300 if(copy_tiles(tile, tile2, copy, copycnt, false, true))
10301 saved = false;
10302 }
10303 }).show();
10304
10305 copy=-1;
10306 tile2=tile=z;
10307 }, nullopt, type != 0 },
10308 };
10309 rcmenu.pop(window_mouse_x(),window_mouse_y());
10310 redraw = true;
10311 r_click = false;
10312 goto REDRAW;
10313 }
10314 update_hw_screen();
10315 }
10316 while(!done);
10317
10318 while(gui_mouse_b())
10319 {
10320 /* do nothing */
10321 rest(1);
10322 }
10323
10324 comeback();
10325 register_blank_tiles();
10326 register_used_tiles();
10327 setup_combo_animations();
10328 setup_combo_animations2();
10329 int32_t ret = done-1;
10330 if(ret)
10331 {
10332 _selected_tile = tile;
10333 _selected_tcset = cs;
10334 }
10335
10336 popup_zqdialog_end();
10337 return ret;
10338 }
10339 int32_t select_tile_2(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
10340 {
10341 if(_selected_tile > -1)
10342 {
10343 tile = _selected_tile;
10344 cs = _selected_tcset;
10345 }
10346 int32_t ret = select_tile(tile,flip,type,cs,edit_cs,exnow,always_use_flip);
10347 if(_selected_tile < 0)
10348 {
10349 _selected_tile = tile;
10350 _selected_tcset = cs;
10351 }
10352 return ret;
10353 }
10354
10355 int32_t onTiles()
10356 {
10357 return onGotoTiles(-1);
10358 }
10359
10360 int32_t onGotoTiles(int32_t startfrom)
10361 {
10362 static int32_t t = 0;
10363 if (startfrom > -1)
10364 t = startfrom;
10365 int32_t f = 0;
10366 int32_t c = CSet;
10367 reset_pal_cycling();
10368 // loadlvlpal(Map.CurrScr()->color);
10369 rebuild_trans_table();
10370 select_tile(t, f, 0, c, true);
10371 refresh(rALL);
10372 return D_O_K;
10373 }
10374
10375 int32_t combopage_animate = 1;
10376 void draw_combo(BITMAP *dest, int x,int y,int c,int cs,bool animate)
10377 {
10378 if(unsigned(c)<MAXCOMBOS)
10379 {
10380 newcombo& cmb = combobuf[c];
10381 int t = cmb.tile;
10382 if(!animate)
10383 cmb.tile = cmb.o_tile;
10384 put_combo(dest,x,y,c,cs,0,0);
10385 cmb.tile = t;
10386 }
10387 else
10388 {
10389 rectfill(dest,x,y,x+32-1,y+32-1,0);
10390 }
10391 }
10392
10393 void draw_combos(int32_t page,int32_t cs,bool cols)
10394 {
10395 clear_bitmap(screen2);
10396 BITMAP *buf = create_bitmap_ex(8,16,16);
10397
10398 int32_t w = 32;
10399 int32_t h = 32;
10400 int32_t mul = 2;
10401
10402 int32_t window_xofs=(zq_screen_w-640-12)>>1;
10403 int32_t window_yofs=(zq_screen_h-480-25-6)>>1;
10404 int32_t screen_xofs=window_xofs+6;
10405 int32_t screen_yofs=window_yofs+25;
10406
10407 if(cols==false)
10408 {
10409 for(int32_t i=0; i<256; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
10410 {
10411 int32_t x = (i%COMBOS_PER_ROW)*w;
10412 int32_t y = (i/COMBOS_PER_ROW)*h;
10413
10414 combotile_override_x = x+screen_xofs+(w-16)/2;
10415 combotile_override_y = y+screen_yofs+(h-16)/2;
10416 draw_combo(buf,0,0,i+(page<<8),cs,combopage_animate);
10417 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10418 }
10419 }
10420 else
10421 {
10422 int32_t c = 0;
10423
10424 for(int32_t i=0; i<256; i++)
10425 {
10426 int32_t x = (i%COMBOS_PER_ROW)*w;
10427 int32_t y = (i/COMBOS_PER_ROW)*h;
10428
10429 combotile_override_x = x+screen_xofs+(w-16)/2;
10430 combotile_override_y = y+screen_yofs+(h-16)/2;
10431 draw_combo(buf,0,0,c+(page<<8),cs,combopage_animate);
10432 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10433 ++c;
10434
10435 if((i&3)==3)
10436 c+=48;
10437
10438 if((i%COMBOS_PER_ROW)==(COMBOS_PER_ROW-1))
10439 c-=256;
10440 }
10441 }
10442 combotile_override_x = combotile_override_y = -1;
10443
10444 for(int32_t x=(64*mul); x<(320*mul); x+=(64*mul))
10445 {
10446 _allegro_vline(screen2,x,0,(208*mul)-1,vc(15));
10447 }
10448
10449 destroy_bitmap(buf);
10450 }
10451
10452 void combo_info(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,int32_t buttons)
10453 {
10454 int32_t yofs=3;
10455 static BITMAP *buf = create_bitmap_ex(8,16,16);
10456 int32_t mul = 2;
10457 FONT *tfont = get_zc_font(font_lfont_l);
10458
10459 rectfill(screen2,0,210*2,(320*2)-1,(240*2)-1,jwin_pal[jcBOX]);
10460 _allegro_hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
10461 _allegro_hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
10462
10463 jwin_draw_frame(screen2,(31*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10464
10465 if(copy>=0)
10466 {
10467 put_combo(buf,0,0,copy,cs,0,0);
10468 stretch_blit(buf,screen2,0,0,16,16,31*mul,216*mul+yofs,16*mul,16*mul);
10469
10470 if(copycnt>1)
10471 {
10472 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
10473 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
10474 }
10475 else
10476 {
10477 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
10478 }
10479 }
10480 else
10481 {
10482 if (InvalidBG == 2)
10483 {
10484 draw_checkerboard(screen2, 31 * mul, 216 * mul + yofs, 16 * mul);
10485 }
10486 else if(InvalidBG == 1)
10487 {
10488 for(int32_t dy=0; dy<16*mul; dy++)
10489 {
10490 for(int32_t dx=0; dx<16*mul; dx++)
10491 {
10492 screen2->line[(216*mul)+yofs+dy][(31*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10493 }
10494 }
10495 }
10496 else
10497 {
10498 rectfill(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(0));
10499 rect(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10500 line(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10501 line(screen2, (31*mul), (216*mul)+yofs+31, (31*mul)+31, (216*mul)+yofs, vc(15));
10502 }
10503 }
10504
10505 jwin_draw_frame(screen2,(53*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10506 put_combo(buf,0,0,tile,cs,0,0);
10507 stretch_blit(buf,screen2,0,0,16,16,53*mul,216*mul+yofs,16*mul,16*mul);
10508
10509 if(tile>tile2)
10510 {
10511 zc_swap(tile,tile2);
10512 }
10513
10514 char cbuf[8];
10515 cbuf[0]=0;
10516
10517 if(tile2!=tile)
10518 {
10519 sprintf(cbuf,"-%d",tile2);
10520 }
10521
10522 textprintf_ex(screen2,tfont,(73*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"combo:");
10523 textprintf_ex(screen2,tfont,(73*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,cbuf);
10524
10525 if(tile2==tile)
10526 {
10527 int32_t nextcombo=combobuf[tile].nextcombo;
10528 int32_t nextcset=(combobuf[tile].animflags & AF_CYCLENOCSET) ? cs : combobuf[tile].nextcset;
10529 jwin_draw_frame(screen2,(136*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10530
10531 if(nextcombo>0)
10532 {
10533 put_combo(buf,0,0,nextcombo,nextcset,0,0);
10534 stretch_blit(buf,screen2,0,0,16,16,136*mul,216*mul+yofs,16*mul,16*mul);
10535 }
10536 else
10537 {
10538 if (InvalidBG == 2)
10539 {
10540 draw_checkerboard(screen2, 136 * mul, 216 * mul + yofs, 16 * mul);
10541 }
10542 else if(InvalidBG == 1)
10543 {
10544 for(int32_t dy=0; dy<16*mul; dy++)
10545 {
10546 for(int32_t dx=0; dx<16*mul; dx++)
10547 {
10548 screen2->line[(216*mul)+yofs+dy][(136*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10549 }
10550 }
10551 }
10552 else
10553 {
10554 rectfill(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(0));
10555 rect(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10556 line(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10557 line(screen2, (136*mul), (216*mul)+yofs+31, (136*mul)+31, (216*mul)+yofs, vc(15));
10558 }
10559 }
10560
10561 textprintf_right_ex(screen2,tfont,(132*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Cycle:");
10562 textprintf_right_ex(screen2,tfont,(132*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",nextcombo);
10563 }
10564
10565
10566 FONT *tf = font;
10567 font = tfont;
10568
10569 draw_checkbox(screen2,320,440+yofs,16,combopage_animate);
10570 textprintf_ex(screen2,tfont,320+18,440+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Animate");
10571
10572 if(buttons&2)
10573 {
10574 draw_text_button(screen2,404,426+yofs,88,42,"Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10575 }
10576
10577 if(buttons&4)
10578 {
10579 draw_text_button(screen2,494,426+yofs,88,42,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10580 }
10581
10582 font = tf;
10583
10584 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
10585 textprintf_ex(screen2,tfont,(293*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
10586 textprintf_centre_ex(screen2,tfont,(309*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
10587 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
10588
10589 int32_t w = 640;
10590 int32_t h = 480;
10591 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10592 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10593 int32_t screen_xofs=window_xofs+6;
10594 int32_t screen_yofs=window_yofs+25;
10595
10596 custom_vsync();
10597 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
10598 SCRFIX();
10599 //destroy_bitmap(buf);
10600 }
10601
10602 void sel_combo(int32_t &tile, int32_t &tile2, int32_t s, bool cols)
10603 {
10604 int32_t page = tile&0xFF00;
10605 tile &= 0xFF;
10606
10607 if(!cols)
10608 tile += s;
10609 else
10610 {
10611 if(s==-COMBOS_PER_ROW)
10612 tile-=4;
10613
10614 if(s==COMBOS_PER_ROW)
10615 tile+=4;
10616
10617 if(s==-1)
10618 tile-=1;
10619
10620 if(s==1)
10621 tile+=1;
10622 }
10623
10624 /*
10625 if(s==1)
10626 {
10627 if((tile&3)==3)
10628 tile+=48;
10629 else
10630 ++tile;
10631 }
10632 if(s==-1)
10633 {
10634 if((tile&3)==0)
10635 tile-=48;
10636 else
10637 --tile;
10638 }
10639 }
10640 */
10641 bound(tile,0,255);
10642 tile += page;
10643
10644 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
10645 tile2 = tile;
10646 }
10647
10648 void draw_combo_list_window()
10649 {
10650 int32_t window_xofs=0;
10651 int32_t window_yofs=0;
10652 int32_t w = 640;
10653 int32_t h = 480;
10654
10655 window_xofs=(zq_screen_w-w-12)>>1;
10656 window_yofs=(zq_screen_h-h-25-6)>>1;
10657 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
10658 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
10659 FONT *oldfont = font;
10660 font = get_zc_font(font_lfont);
10661 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Combo", true);
10662 font=oldfont;
10663 }
10664
10665
10666 static int32_t _selected_combo=-1, _selected_cset=-1;
10667 bool select_combo_2(int32_t &cmb,int32_t &cs)
10668 {
10669 popup_zqdialog_start();
10670 reset_combo_animations();
10671 reset_combo_animations2();
10672 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
10673 // static int32_t cmb=0;
10674 int32_t page=cmb>>8;
10675 int32_t tile2=cmb;
10676 int32_t done=0;
10677 int32_t tile_clicked=-1;
10678 int32_t t2;
10679 // int32_t cs = CSet;
10680 int32_t copy=-1;
10681 int32_t copycnt=0;
10682
10683 position_mouse_z(0);
10684
10685 go();
10686 int32_t w = 640;
10687 int32_t h = 480;
10688 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10689 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10690 int32_t screen_xofs=window_xofs+6;
10691 int32_t screen_yofs=window_yofs+25;
10692 int32_t panel_yofs=3;
10693 int32_t mul = 2;
10694 FONT *tfont = get_zc_font(font_lfont_l);
10695
10696 draw_combo_list_window();
10697 draw_combos(page,cs,combo_cols);
10698 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
10699
10700 while(gui_mouse_b())
10701 {
10702 /* do nothing */
10703 rest(1);
10704 }
10705
10706 bool bdown=false;
10707 int32_t f=0;
10708 int otl = cmb, otl2 = tile2;
10709
10710 do
10711 {
10712 HANDLE_CLOSE_ZQDLG();
10713 if(exiting_program) break;
10714 rest(4);
10715 bool redraw=false;
10716
10717 if(mouse_z<0)
10718 {
10719 if(page<COMBO_PAGES-1)
10720 {
10721 ++page;
10722 cmb=tile2=(page<<8)+(cmb&0xFF);
10723 }
10724
10725 position_mouse_z(0);
10726 redraw=true;
10727 }
10728 else if(mouse_z>0)
10729 {
10730 if(page>0)
10731 {
10732 --page;
10733 cmb=tile2=(page<<8)+(cmb&0xFF);
10734 }
10735
10736 position_mouse_z(0);
10737 redraw=true;
10738 }
10739
10740 if(keypressed())
10741 {
10742 switch(readkey()>>8)
10743 {
10744 case KEY_DEL:
10745 cmb=0;
10746 done=2;
10747 break;
10748
10749 case KEY_ENTER_PAD:
10750 case KEY_ENTER:
10751 done=2;
10752 break;
10753
10754 case KEY_ESC:
10755 done=1;
10756 break;
10757
10758 case KEY_F1:
10759 onHelp();
10760 break;
10761
10762 case KEY_SPACE:
10763 combo_cols=!combo_cols;
10764 redraw=true;
10765 break;
10766
10767 case KEY_EQUALS:
10768 case KEY_PLUS_PAD:
10769 cs = (cs<13) ? cs+1:0;
10770 redraw=true;
10771 break;
10772
10773 case KEY_MINUS:
10774 case KEY_MINUS_PAD:
10775 cs = (cs>0) ? cs-1:13;
10776 redraw=true;
10777 break;
10778
10779 case KEY_UP:
10780 sel_combo(cmb,tile2,-COMBOS_PER_ROW,combo_cols);
10781 redraw=true;
10782 break;
10783
10784 case KEY_DOWN:
10785 sel_combo(cmb,tile2,COMBOS_PER_ROW,combo_cols);
10786 redraw=true;
10787 break;
10788
10789 case KEY_LEFT:
10790 sel_combo(cmb,tile2,-1,combo_cols);
10791 redraw=true;
10792 break;
10793
10794 case KEY_RIGHT:
10795 sel_combo(cmb,tile2,1,combo_cols);
10796 redraw=true;
10797 break;
10798
10799 case KEY_PGUP:
10800 if(page>0)
10801 {
10802 --page;
10803 cmb=tile2=(page<<8)+(cmb&0xFF);
10804 }
10805
10806 redraw=true;
10807 break;
10808
10809 case KEY_PGDN:
10810 if(page<COMBO_PAGES-1)
10811 {
10812 ++page;
10813 cmb=tile2=(page<<8)+(cmb&0xFF);
10814 }
10815
10816 redraw=true;
10817 break;
10818
10819 case KEY_P:
10820 {
10821 int32_t choosepage=getnumber("Goto Page", (PreFillComboEditorPage?page:0));
10822
10823 if(!cancelgetnum)
10824 page=(zc_min(choosepage,COMBO_PAGES-1));
10825
10826 cmb=tile2=(page<<8)+(cmb&0xFF);
10827 redraw=true;
10828 break;
10829 }
10830 }
10831
10832 clear_keybuf();
10833 }
10834
10835 if(gui_mouse_b()&1)
10836 {
10837 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
10838 {
10839 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
10840 {
10841 done=1;
10842 }
10843 }
10844
10845 int32_t x=gui_mouse_x()-screen_xofs;
10846 int32_t y=gui_mouse_y()-screen_yofs;
10847
10848 if(y>=0 && y<208*mul)
10849 {
10850 x=zc_min(zc_max(x,0),(320*mul)-1);
10851 int32_t t;
10852
10853 if(!combo_cols)
10854 {
10855 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
10856 }
10857 else
10858 {
10859 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10860 }
10861
10862 bound(t,0,255);
10863 t+=page<<8;
10864 cmb=tile2=t;
10865
10866 if(tile_clicked!=t)
10867 {
10868 dclick_status=DCLICK_NOT;
10869 }
10870 else if(dclick_status == DCLICK_AGAIN)
10871 {
10872 while(gui_mouse_b())
10873 {
10874 /* do nothing */
10875 }
10876
10877 if(!combo_cols)
10878 {
10879 t2 = (y>>5)*COMBOS_PER_ROW + (x>>5);
10880 }
10881 else
10882 {
10883 t2 = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10884 }
10885
10886 if(t2!=t)
10887 {
10888 dclick_status=DCLICK_NOT;
10889 }
10890 else
10891 {
10892 done=2;
10893 }
10894 }
10895
10896 tile_clicked=t;
10897 }
10898 else if(y>=(208*mul) && x>(300*mul) && !bdown)
10899 {
10900 if(y<(224*mul)+panel_yofs && page>0)
10901 {
10902 --page;
10903 redraw=true;
10904 }
10905
10906 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
10907 {
10908 ++page;
10909 redraw=true;
10910 }
10911
10912 bdown=true;
10913 }
10914
10915 if(!bdown && isinRect(x,y,(247*mul),(213*mul),((247+44)*mul),((213+21)*mul)))
10916 {
10917 FONT *tf = font;
10918 font = tfont;
10919
10920 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
10921 {
10922 done=2;
10923 }
10924
10925 font = tf;
10926 }
10927 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
10928 {
10929 FONT *tf = font;
10930 font = tfont;
10931
10932 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
10933 combopage_animate = combopage_animate ? 0 : 1;
10934 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
10935 redraw = true;
10936
10937 font = tf;
10938 }
10939
10940 bdown=true;
10941 }
10942
10943 bool r_click = false;
10944
10945 if(gui_mouse_b()&2 && !bdown)
10946 {
10947 int32_t x=gui_mouse_x()+screen_xofs;
10948 int32_t y=gui_mouse_y()+screen_yofs;
10949
10950 if(y>=0 && y<208*mul)
10951 {
10952 x=zc_min(zc_max(x,0),(320*mul)-1);
10953 int32_t t;
10954
10955 if(!combo_cols)
10956 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
10957 else
10958 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10959
10960 bound(t,0,255);
10961 t+=page<<8;
10962
10963 if(t<zc_min(cmb,tile2) || t>zc_max(cmb,tile2))
10964 cmb=tile2=t;
10965 }
10966
10967 bdown = r_click = true;
10968 f=8;
10969 }
10970
10971 if(gui_mouse_b()==0)
10972 bdown=false;
10973
10974 if((f%8) || InvalidBG == 1)
10975 redraw = true;
10976 if(otl != cmb || otl2 != tile2)
10977 {
10978 otl = cmb;
10979 otl2 = tile2;
10980 redraw = true;
10981 }
10982
10983 if(redraw || combopage_animate)
10984 draw_combos(page,cs,combo_cols);
10985
10986 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
10987
10988 if(f&8)
10989 {
10990 int32_t x,y;
10991
10992 for(int32_t i=zc_min(cmb,tile2); i<=zc_max(cmb,tile2); i++)
10993 {
10994 if((i>>8)==page)
10995 {
10996 int32_t t=i&255;
10997
10998 if(!combo_cols)
10999 {
11000 x=(t%COMBOS_PER_ROW)<<5;
11001 y=(t/COMBOS_PER_ROW)<<5;
11002 }
11003 else
11004 {
11005 x=((t&3) + ((t/52)<<2)) << 5;
11006 y=((t%52)>>2) << 5;
11007 }
11008
11009 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11010 }
11011 }
11012
11013 SCRFIX();
11014 }
11015
11016 ++f;
11017
11018 }
11019 while(!done);
11020
11021 while(gui_mouse_b())
11022 {
11023 /* do nothing */
11024 rest(1);
11025 }
11026
11027 comeback();
11028 setup_combo_animations();
11029 setup_combo_animations2();
11030
11031 bool ret = done==2;
11032 if(ret)
11033 {
11034 _selected_combo = cmb;
11035 _selected_cset = cs;
11036 }
11037
11038 popup_zqdialog_end();
11039 return ret;
11040 }
11041
11042 bool select_combo_3(int32_t &cmb,int32_t &cs)
11043 {
11044 if(_selected_combo < 0)
11045 {
11046 _selected_combo = Combo;
11047 _selected_cset = CSet;
11048 }
11049 cmb = _selected_combo;
11050 cs = _selected_cset;
11051 return select_combo_2(cmb,cs);
11052 }
11053
11054 bool advpaste(int32_t tile, int32_t tile2, int32_t copy)
11055 {
11056 static bitstring pasteflags;
11057 static const vector<CheckListInfo> advp_names =
11058 {
11059 { "Tile" },
11060 { "CSet2" },
11061 { "Solidity" },
11062 { "Animation" },
11063 { "Type" },
11064 { "Inherent Flag" },
11065 { "Attribytes" },
11066 { "Attrishorts" },
11067 { "Attributes" },
11068 { "Flags", "The 16 Flags on the 'Flags' tab" },
11069 { "Gen. Flags", "The 2 'General Flags' on the 'Flags' tab" },
11070 { "Label" },
11071 { "Script" },
11072 { "Effect" },
11073 { "Triggers Tab" },
11074 { "Lifting Tab" },
11075 { "Gen: Movespeed", "The Movespeed related values from the 'General' tab" },
11076 { "Gen: SFX", "The SFX related values from the 'General' tab" },
11077 { "Gen: Sprites", "The Sprites related values from the 'General' tab" },
11078 };
11079 if(!call_checklist_dialog("Advanced Paste",advp_names,pasteflags))
11080 return false;
11081
11082 //Paste to each combo in the range
11083 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11084 {
11085 combobuf[i].advpaste(combobuf[copy], pasteflags);
11086 }
11087
11088 if(pasteflags.get(CMB_ADVP_TILE)) //reset animations if needed
11089 {
11090 setup_combo_animations();
11091 setup_combo_animations2();
11092 }
11093
11094 return true;
11095 }
11096
11097 int32_t combo_screen(int32_t pg, int32_t tl)
11098 {
11099 popup_zqdialog_start();
11100 reset_combo_animations();
11101 reset_combo_animations2();
11102 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
11103 static int32_t tile=0;
11104 static int32_t page=0;
11105
11106 if(pg>-1)
11107 page = pg;
11108
11109 if(tl>-1)
11110 tile = tl;
11111
11112 int32_t tile2=tile;
11113 int32_t done=0;
11114 int32_t cs = CSet;
11115 int32_t copy=-1;
11116 int32_t copycnt=0;
11117
11118 int32_t tile_clicked=-1;
11119 int32_t t2;
11120
11121 bool masscopy;
11122
11123 go();
11124 int32_t w = 640;
11125 int32_t h = 480;
11126 int32_t window_xofs=(zq_screen_w-w-12)>>1;
11127 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
11128 int32_t screen_xofs=window_xofs+6;
11129 int32_t screen_yofs=window_yofs+25;
11130 int32_t panel_yofs=3;
11131 int32_t mul = 2;
11132 FONT *tfont = get_zc_font(font_lfont_l);
11133
11134 draw_combo_list_window();
11135 draw_combos(page,cs,combo_cols);
11136 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11137 go_combos();
11138 position_mouse_z(0);
11139
11140 while(gui_mouse_b())
11141 {
11142 /* do nothing */
11143 }
11144
11145 bool bdown=false;
11146 int32_t f=0;
11147 int otl = tile, otl2 = tile2;
11148
11149 do
11150 {
11151 HANDLE_CLOSE_ZQDLG();
11152 if(exiting_program) break;
11153 rest(4);
11154 bool redraw=false;
11155
11156 if(mouse_z<0)
11157 {
11158 if(page<COMBO_PAGES-1)
11159 {
11160 ++page;
11161 tile=tile2=(page<<8)+(tile&0xFF);
11162 }
11163
11164 position_mouse_z(0);
11165 redraw=true;
11166 }
11167 else if(mouse_z>0)
11168 {
11169 if(page>0)
11170 {
11171 --page;
11172 tile=tile2=(page<<8)+(tile&0xFF);
11173 }
11174
11175 position_mouse_z(0);
11176 redraw=true;
11177 }
11178
11179 if(keypressed())
11180 {
11181 switch(readkey()>>8)
11182 {
11183 case KEY_ENTER_PAD:
11184 case KEY_ENTER:
11185 done=2;
11186 break;
11187
11188 case KEY_ESC:
11189 done=1;
11190 break;
11191
11192 case KEY_F1:
11193 onHelp();
11194 break;
11195
11196 case KEY_SPACE:
11197 combo_cols=!combo_cols;
11198 redraw=true;
11199 break;
11200
11201 case KEY_EQUALS:
11202 case KEY_PLUS_PAD:
11203 if(CHECK_CTRL_CMD)
11204 {
11205 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11206 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11207 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11208
11209 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11210 {
11211 combobuf[i].set_tile(wrap(combobuf[i].o_tile + amnt,
11212 0, NEWMAXTILES-1));
11213 }
11214
11215 setup_combo_animations();
11216 redraw=true;
11217 }
11218 else
11219 {
11220 cs = (cs<13) ? cs+1:0;
11221 redraw=true;
11222 }
11223
11224 break;
11225
11226 case KEY_MINUS:
11227 case KEY_MINUS_PAD:
11228 if(CHECK_CTRL_CMD)
11229 {
11230 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11231 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11232 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11233
11234 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11235 {
11236 combobuf[i].set_tile(wrap(combobuf[i].o_tile - amnt,
11237 0, NEWMAXTILES-1));
11238 }
11239
11240 setup_combo_animations();
11241 redraw=true;
11242 }
11243 else
11244 {
11245 cs = (cs>0) ? cs-1:13;
11246 redraw=true;
11247 }
11248
11249 break;
11250
11251 case KEY_UP:
11252 sel_combo(tile,tile2,-COMBOS_PER_ROW,combo_cols);
11253 redraw=true;
11254 break;
11255
11256 case KEY_DOWN:
11257 sel_combo(tile,tile2,COMBOS_PER_ROW,combo_cols);
11258 redraw=true;
11259 break;
11260
11261 case KEY_LEFT:
11262 sel_combo(tile,tile2,-1,combo_cols);
11263 redraw=true;
11264 break;
11265
11266 case KEY_RIGHT:
11267 sel_combo(tile,tile2,1,combo_cols);
11268 redraw=true;
11269 break;
11270
11271 case KEY_PGUP:
11272 if(page>0)
11273 {
11274 --page;
11275 tile=tile2=(page<<8)+(tile&0xFF);
11276 }
11277
11278 redraw=true;
11279 break;
11280
11281 case KEY_PGDN:
11282 if(page<COMBO_PAGES-1)
11283 {
11284 ++page;
11285 tile=tile2=(page<<8)+(tile&0xFF);
11286 }
11287
11288 redraw=true;
11289 break;
11290
11291 case KEY_A:
11292 {
11293 tile=(page<<8);
11294 tile2=(page<<8)+(0xFF);
11295 }
11296
11297 redraw=true;
11298 break;
11299
11300 case KEY_P:
11301 {
11302 int32_t choosepage = getnumber("Goto Page", (PreFillComboEditorPage?page:0));
11303
11304 if(!cancelgetnum)
11305 page=(zc_min(choosepage,COMBO_PAGES-1));
11306
11307 tile=tile2=(page<<8)+(tile&0xFF);
11308 redraw=true;
11309 }
11310 break;
11311
11312 case KEY_U:
11313 comeback_combos();
11314 redraw=true;
11315 break;
11316
11317 case KEY_E:
11318 go_combos();
11319 edit_combo(tile,false,cs);
11320 redraw=true;
11321 setup_combo_animations();
11322 setup_combo_animations2();
11323 break;
11324
11325 case KEY_C:
11326 go_combos();
11327 copy=zc_min(tile,tile2);
11328 copycnt=abs(tile-tile2)+1;
11329 redraw=true;
11330 break;
11331
11332 case KEY_H:
11333 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11334 {
11335 combobuf[i].flip^=1;
11336 byte w2=combobuf[i].walk;
11337 combobuf[i].walk=((w2& ~0x33)>>2 | (w2&0x33)<<2);
11338 w2=combobuf[i].csets;
11339 combobuf[i].csets= (((w2& ~0x50)>>1 | (w2&0x50)<<1) & ~0x0F) | (w2 & 0x0F);
11340 }
11341
11342 redraw=true;
11343 saved=false;
11344 break;
11345
11346 case KEY_M:
11347 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
11348 {
11349 move_combos(tile,tile2,copy,copycnt);
11350 saved=false;
11351 }
11352
11353 redraw=true;
11354 break;
11355
11356 case KEY_S:
11357 tile=tile2=zc_min(tile,tile2);
11358
11359 if(copy>=0 && tile!=copy)
11360 {
11361 go_combos();
11362
11363 for(int32_t i=0; i<copycnt; i++)
11364 {
11365 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11366 }
11367
11368 saved=false;
11369 setup_combo_animations();
11370 setup_combo_animations2();
11371 }
11372
11373 redraw=true;
11374 copy=-1;
11375 break;
11376
11377 case KEY_V:
11378 if((CHECK_CTRL_CMD) && copy != -1)
11379 {
11380 if(advpaste(tile, tile2, copy))
11381 {
11382 saved=false;
11383 redraw=true;
11384 copy=-1;
11385 }
11386
11387 break;
11388 }
11389
11390 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11391
11392 if(copy==-1)
11393 {
11394 go_combos();
11395
11396 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11397 {
11398 combobuf[i].flip^=2;
11399 byte w2=combobuf[i].walk;
11400 combobuf[i].walk=(w2&0x55)<<1 | (w2& ~0x55)>>1;
11401 w2=combobuf[i].csets;
11402 combobuf[i].csets= (((w2&0x30)<<2 | (w2& ~0x30)>>2) & ~0x0F) | (w2 & 0x0F);
11403 }
11404
11405 saved=false;
11406 }
11407 else
11408 {
11409 go_combos();
11410 copy_combos(tile,tile2,copy,copycnt,masscopy);
11411 setup_combo_animations();
11412 setup_combo_animations2();
11413 saved=false;
11414 }
11415
11416 redraw=true;
11417 break;
11418 case KEY_R:
11419 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11420 {
11421 combobuf[i].flip = rotate_value(combobuf[i].flip);
11422 combobuf[i].walk = rotate_walk(combobuf[i].walk);
11423 combobuf[i].csets = rotate_cset(combobuf[i].csets);
11424 }
11425
11426 redraw=true;
11427 saved=false;
11428 break;
11429
11430 case KEY_I:
11431 {
11432 // rev.1509; Can now insert/remove all selected combos
11433 int32_t z=tile;
11434 int32_t numSelected = abs(tile-tile2) + 1;
11435 tile=zc_min(tile,tile2);
11436 tile2=MAXCOMBOS;
11437 copy = tile + numSelected; // copy=tile+1;
11438 copycnt = MAXCOMBOS-tile-numSelected; // copycnt=MAXCOMBOS-tile;
11439
11440 if(key[KEY_LSHIFT]||key[KEY_RSHIFT])
11441 {
11442 char buf[64];
11443
11444 if(numSelected>1)
11445 sprintf(buf,"Remove combos %d - %d?",tile, copy-1);
11446 else
11447 sprintf(buf,"Remove combo %d?",tile);
11448
11449 if(jwin_alert("Confirm Remove",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11450 {
11451 move_combos(tile,tile2,copy, copycnt);
11452 //don't allow the user to undo; quest combo references are incorrect -DD
11453 go_combos();
11454 redraw=true;
11455 saved=false;
11456 }
11457 }
11458 else
11459 {
11460 char buf[64];
11461
11462 if(numSelected>1)
11463 sprintf(buf,"Insert %d blank combos?",numSelected);
11464 else
11465 sprintf(buf,"Insert a blank combo?");
11466
11467 if(jwin_alert("Confirm Insert",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11468 {
11469 move_combos(copy,tile2,tile, copycnt);
11470 go_combos();
11471 redraw=true;
11472 saved=false;
11473 }
11474 }
11475
11476 copy=-1;
11477 tile2=tile=z;
11478 }
11479 break;
11480
11481 case KEY_DEL:
11482 {
11483 char buf[40];
11484
11485 if(tile==tile2)
11486 {
11487 sprintf(buf,"Delete combo %d?",tile);
11488 }
11489 else
11490 {
11491 sprintf(buf,"Delete combos %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
11492 }
11493
11494 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11495 {
11496 go_combos();
11497
11498 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11499 {
11500 clear_combo(i);
11501 }
11502
11503 tile=tile2=zc_min(tile,tile2);
11504 redraw=true;
11505 saved=false;
11506 setup_combo_animations();
11507 setup_combo_animations2();
11508 }
11509 }
11510 break;
11511 }
11512
11513 clear_keybuf();
11514 }
11515
11516 if(gui_mouse_b()&1)
11517 {
11518 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
11519 {
11520 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
11521 {
11522 done=1;
11523 }
11524 }
11525
11526 int32_t x=gui_mouse_x()-screen_xofs;
11527 int32_t y=gui_mouse_y()-screen_yofs;
11528
11529 if(y>=0 && y<(208*mul))
11530 {
11531 x=zc_min(zc_max(x,0),(320*mul)-1);
11532 int32_t t;
11533
11534 if(!combo_cols)
11535 {
11536 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
11537 }
11538 else
11539 {
11540 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11541 }
11542
11543 bound(t,0,255);
11544 t+=page<<8;
11545
11546 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
11547 {
11548 tile2=t;
11549 }
11550 else
11551 {
11552 tile=tile2=t;
11553 }
11554
11555 if(tile_clicked!=t)
11556 {
11557 dclick_status=DCLICK_NOT;
11558 }
11559 else if(dclick_status == DCLICK_AGAIN)
11560 {
11561 while(gui_mouse_b())
11562 {
11563 /* do nothing */
11564 rest(1);
11565 }
11566
11567 if(!combo_cols)
11568 {
11569 t2 = (y>>4)*COMBOS_PER_ROW + (x>>4);
11570 }
11571 else
11572 {
11573 t2 = ((x>>6)*52) + ((x>>4)&3) + ((y>>4)<<2);
11574 }
11575
11576 bound(t2,0,255);
11577 t2+=page<<8;
11578
11579 if(t2!=t)
11580 {
11581 dclick_status=DCLICK_NOT;
11582 }
11583 else
11584 {
11585 go_combos();
11586 edit_combo(tile,false,cs);
11587 redraw=true;
11588 setup_combo_animations();
11589 setup_combo_animations2();
11590 }
11591 }
11592
11593 tile_clicked=t;
11594 }
11595 else if(x>(300*mul) && !bdown)
11596 {
11597 if(y<(224*mul)+panel_yofs && page>0)
11598 {
11599 --page;
11600 redraw=true;
11601 }
11602
11603 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
11604 {
11605 ++page;
11606 redraw=true;
11607 }
11608
11609 bdown=true;
11610 }
11611
11612 if(!bdown && isinRect(x,y,(202*mul),(213*mul)+panel_yofs,(202+44)*mul,(213+21)*mul))
11613 {
11614 FONT *tf = font;
11615 font = tfont;
11616
11617 if(do_text_button((202*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Edit"))
11618 {
11619 font = tf;
11620 edit_combo(tile,false,cs);
11621 redraw=true;
11622 }
11623
11624 font = tf;
11625 }
11626 else if(!bdown && isinRect(x,y,(247*mul),(213*mul)+panel_yofs,(247+44)*mul,(213+21)*mul))
11627 {
11628 FONT *tf = font;
11629 font = tfont;
11630
11631 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
11632 {
11633 done=1;
11634 }
11635
11636 font = tf;
11637 }
11638 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
11639 {
11640 FONT *tf = font;
11641 font = tfont;
11642
11643 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
11644 combopage_animate = combopage_animate ? 0 : 1;
11645 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
11646 redraw = true;
11647
11648 font = tf;
11649 }
11650
11651 bdown=true;
11652 }
11653
11654 bool r_click = false;
11655
11656 if(gui_mouse_b()&2 && !bdown)
11657 {
11658 int32_t x=gui_mouse_x()-screen_xofs;
11659 int32_t y=gui_mouse_y()-screen_yofs;
11660
11661 if(y>=0 && y<(208*mul))
11662 {
11663 x=zc_min(zc_max(x,0),(320*mul)-1);
11664 int32_t t;
11665
11666 if(!combo_cols)
11667 {
11668 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
11669 }
11670 else
11671 {
11672 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11673 }
11674
11675 bound(t,0,255);
11676 t+=page<<8;
11677
11678 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
11679 {
11680 tile=tile2=t;
11681 }
11682 }
11683
11684 bdown = r_click = true;
11685 f=8;
11686 }
11687
11688 REDRAW:
11689
11690 if(gui_mouse_b()==0)
11691 bdown=false;
11692
11693 if((f%8) || InvalidBG == 1)
11694 redraw = true;
11695 if(otl != tile || otl2 != tile2)
11696 {
11697 otl = tile;
11698 otl2 = tile2;
11699 redraw = true;
11700 }
11701
11702 if(redraw || combopage_animate)
11703 draw_combos(page,cs,combo_cols);
11704
11705 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11706
11707 if(f&8)
11708 {
11709 int32_t x,y;
11710
11711 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11712 {
11713 if((i>>8)==page)
11714 {
11715 int32_t t=i&255;
11716
11717 if(!combo_cols)
11718 {
11719 x=(t%COMBOS_PER_ROW)<<5;
11720 y=(t/COMBOS_PER_ROW)<<5;
11721 }
11722 else
11723 {
11724 x=((t&3) + ((t/52)<<2)) << 5;
11725 y=((t%52)>>2) << 5;
11726 }
11727
11728 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11729 }
11730 }
11731
11732 SCRFIX();
11733 }
11734
11735 ++f;
11736
11737 //Seriously? There is duplicate code for the r-click menu? -Gleeok
11738 if(r_click)
11739 {
11740 NewMenu rcmenu
11741 {
11742 { "Copy", [&]()
11743 {
11744 go_combos();
11745 copy=zc_min(tile,tile2);
11746 copycnt=abs(tile-tile2)+1;
11747 } },
11748 { "Paste", [&]()
11749 {
11750 if((CHECK_CTRL_CMD) && copy != -1)
11751 {
11752 if(advpaste(tile, tile2, copy))
11753 {
11754 saved=false;
11755 redraw=true;
11756 copy=-1;
11757 }
11758 return;
11759 }
11760
11761 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11762
11763 if(copy>-1)
11764 {
11765 go_combos();
11766 copy_combos(tile,tile2,copy,copycnt,masscopy);
11767 setup_combo_animations();
11768 setup_combo_animations2();
11769 saved=false;
11770 }
11771 } },
11772 { "Adv. Paste", [&]()
11773 {
11774 if(copy > -1)
11775 {
11776 if(advpaste(tile, tile2, copy))
11777 {
11778 saved=false;
11779 redraw=true;
11780 copy=-1;
11781 }
11782 }
11783 } },
11784 { "Swap", [&]()
11785 {
11786 tile=tile2=zc_min(tile,tile2);
11787
11788 if(copy>=0 && tile!=copy)
11789 {
11790 go_combos();
11791
11792 for(int32_t i=0; i<copycnt; i++)
11793 {
11794 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11795 }
11796
11797 saved=false;
11798 setup_combo_animations();
11799 setup_combo_animations2();
11800 }
11801 copy=-1;
11802 } },
11803 { "Delete", [&]()
11804 {
11805 string msg;
11806
11807 if(tile==tile2)
11808 msg = fmt::format("Delete combo {}?",tile);
11809 else
11810 msg = fmt::format("Delete combos {}-{}?",zc_min(tile,tile2),zc_max(tile,tile2));
11811 bool didconfirm = false;
11812 AlertDialog("Confirm Delete",msg,
11813 [&](bool ret,bool)
11814 {
11815 if(ret)
11816 didconfirm = true;
11817 }).show();
11818 if(didconfirm)
11819 {
11820 go_combos();
11821
11822 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11823 clear_combo(i);
11824
11825 tile=tile2=zc_min(tile,tile2);
11826 saved=false;
11827 }
11828 } },
11829 {},
11830 { "Edit", [&]()
11831 {
11832 go_combos();
11833 edit_combo(tile,false,cs);
11834 } },
11835 { "Insert", [&]()
11836 {
11837 int z = tile;
11838 int count = abs(tile-tile2)+1;
11839 tile = zc_min(tile,tile2);
11840 tile2 = MAXCOMBOS;
11841 copy = tile+count;
11842 copycnt = MAXCOMBOS-tile-count;
11843
11844 string msg;
11845
11846 if(count>1)
11847 msg = fmt::format("Insert combos {} - {}?"
11848 " This will offset all of the combos that follow!",tile, copy-1);
11849 else
11850 msg = fmt::format("Insert combo {}?"
11851 " This will offset all of the combos that follow!",tile);
11852
11853 bool didconfirm = false;
11854 AlertDialog("Confirm Insert",msg,
11855 [&](bool ret,bool)
11856 {
11857 if(ret)
11858 didconfirm = true;
11859 }).show();
11860 if(didconfirm)
11861 move_combos(copy, tile2, tile, copycnt);
11862 else return;
11863
11864 copy = -1;
11865 tile2 = tile = z;
11866
11867 //don't allow the user to undo; quest combo references are incorrect -DD
11868 go_combos();
11869 saved = false;
11870 } },
11871 { "Remove", [&]()
11872 {
11873 int z = tile;
11874 int count = abs(tile-tile2)+1;
11875 tile = zc_min(tile,tile2);
11876 tile2 = MAXCOMBOS;
11877 copy = tile+count;
11878 copycnt = MAXCOMBOS-tile-count;
11879
11880 string msg;
11881
11882 if(count>1)
11883 msg = fmt::format("Remove combos {} - {}?"
11884 " This will offset all of the combos that follow!",tile, copy-1);
11885 else
11886 msg = fmt::format("Remove combo {}?"
11887 " This will offset all of the combos that follow!",tile);
11888
11889 bool didconfirm = false;
11890 AlertDialog("Confirm Remove",msg,
11891 [&](bool ret,bool)
11892 {
11893 if(ret)
11894 didconfirm = true;
11895 }).show();
11896 if(didconfirm)
11897 move_combos(tile, tile2, copy, copycnt);
11898 else return;
11899
11900 copy = -1;
11901 tile2 = tile = z;
11902
11903 //don't allow the user to undo; quest combo references are incorrect -DD
11904 go_combos();
11905 saved = false;
11906 } },
11907 {},
11908 { "Locations", [&]()
11909 {
11910 int32_t z = Combo;
11911 Combo = tile;
11912 onComboLocationReport();
11913 Combo = z;
11914 } },
11915 };
11916 rcmenu.pop(window_mouse_x(),window_mouse_y());
11917 redraw = true;
11918 r_click = false;
11919 goto REDRAW;
11920 }
11921
11922 }
11923 while(!done);
11924
11925 while(gui_mouse_b())
11926 rest(1);
11927 comeback();
11928 setup_combo_animations();
11929 setup_combo_animations2();
11930 _selected_combo = tile;
11931 _selected_cset = cs;
11932 popup_zqdialog_end();
11933 return done-1;
11934 }
11935
11936 int32_t onCombos()
11937 {
11938 // reset_combo_animations();
11939 combo_screen(-1,-1);
11940 // setup_combo_animations();
11941 refresh(rALL);
11942 return D_O_K;
11943 }
11944
11945 int32_t d_ctile_proc(int32_t msg,DIALOG *d,int32_t c)
11946 {
11947 //these are here to bypass compiler warnings about unused arguments
11948 d=d;
11949 c=c;
11950
11951 if(msg==MSG_CLICK)
11952 {
11953 int32_t t=curr_combo.o_tile;
11954 int32_t f=curr_combo.flip;
11955
11956 if(select_tile(t,f,1,CSet,true,0,true))
11957 {
11958 curr_combo.tile=t;
11959 curr_combo.o_tile=t;
11960 curr_combo.flip=f;
11961 return D_REDRAW;
11962 }
11963 }
11964
11965 return D_O_K;
11966 }
11967
11968 int32_t d_combo_loader(int32_t msg,DIALOG *d,int32_t c)
11969 {
11970 //these are here to bypass compiler warnings about unused arguments
11971 c=c;
11972
11973 if(msg==MSG_DRAW)
11974 {
11975 FONT *f = get_zc_font(font_lfont_l);
11976 textprintf_ex(screen,f,d->x,d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Tile:");
11977 textprintf_ex(screen,f,d->x+((1.5)*36),d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.o_tile);
11978 textprintf_ex(screen,f,d->x,d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
11979 textprintf_ex(screen,f,d->x+((1.5)*36),d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.flip);
11980 textprintf_ex(screen,f,d->x,d->y+(36),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet2:");
11981 }
11982
11983 return D_O_K;
11984 }
11985
11986 int32_t click_d_ctile_proc()
11987 {
11988 d_ctile_proc(MSG_CLICK,NULL,0);
11989 return D_REDRAW;
11990 }
11991
11992 int32_t click_d_combo_proc();
11993
11994 const char *comboscriptdroplist(int32_t index, int32_t *list_size)
11995 {
11996 if(index<0)
11997 {
11998 *list_size = bidcomboscripts_cnt;
11999 return NULL;
12000 }
12001
12002 return bidcomboscripts[index].first.c_str();
12003 }
12004 8 ListData comboscript_list(comboscriptdroplist, &font);
12005
12006 bool call_combo_editor(int32_t);
12007 bool edit_combo(int32_t c,bool freshen,int32_t cs)
12008 {
12009 FONT* ofont = font;
12010 //CSet = cs;
12011 reset_combo_animations();
12012 reset_combo_animations2();
12013 bool edited = call_combo_editor(c);
12014 font = ofont;
12015
12016 if(freshen)
12017 {
12018 refresh(rALL);
12019 }
12020
12021 setup_combo_animations();
12022 setup_combo_animations2();
12023
12024 return edited;
12025 }
12026
12027 int32_t d_itile_proc(int32_t msg,DIALOG *d,int32_t)
12028 {
12029 switch(msg)
12030 {
12031 case MSG_CLICK:
12032 {
12033 int32_t cs = d->d2;
12034 int32_t f = 0;
12035
12036 if(select_tile(d->d1,f,1,cs,true))
12037 {
12038 int32_t ok=1;
12039
12040 if(newtilebuf[d->d1].format==tf8Bit)
12041 jwin_alert("Warning",
12042 "You have selected an 8-bit tile.",
12043 "It will not be drawn correctly",
12044 "on the file select screen.",
12045 "&OK",NULL,'o',0,get_zc_font(font_lfont));
12046
12047 return D_REDRAW;
12048 }
12049 }
12050 break;
12051
12052 case MSG_DRAW:
12053 d->w = 32+4;
12054 d->h = 32+4;
12055
12056 BITMAP *buf = create_bitmap_ex(8,16,16);
12057 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12058
12059 if(buf && bigbmp)
12060 {
12061 clear_bitmap(buf);
12062 overtile16(buf,d->d1,0,0,d->fg,0);
12063 stretch_blit(buf, bigbmp, 0,0, 16, 16, 2, 2, d->w-4, d->h-4);
12064 destroy_bitmap(buf);
12065 jwin_draw_frame(bigbmp,0, 0, d->w,d->h, FR_DEEP);
12066 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12067 destroy_bitmap(bigbmp);
12068 }
12069
12070 break;
12071 }
12072
12073 return D_O_K;
12074 }
12075
12076 static DIALOG icon_dlg[] =
12077 {
12078 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
12079 { jwin_win_proc, 70, 70, 170, 104, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Game Icons", NULL, NULL },
12080 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
12081 { d_itile_proc, 108+3, 112, 20, 20, 0, 0, 0, 0, 0, 6, NULL, NULL, NULL },
12082 { d_itile_proc, 138+3, 112, 20, 20, 0, 0, 0, 0, 0, 7, NULL, NULL, NULL },
12083 { d_itile_proc, 168+3, 112, 20, 20, 0, 0, 0, 0, 0, 8, NULL, NULL, NULL },
12084 { d_itile_proc, 198+3, 112, 20, 20, 0, 0, 0, 0, 0, 9, NULL, NULL, NULL },
12085 { jwin_button_proc, 90, 145, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12086 { jwin_button_proc, 170, 145, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12087 { jwin_text_proc, 108+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "0", NULL, NULL },
12088 { jwin_text_proc, 138+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "1", NULL, NULL },
12089 { jwin_text_proc, 168+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "2", NULL, NULL },
12090 { jwin_text_proc, 198+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "3+", NULL, NULL },
12091 { jwin_text_proc, 88, 98, 12, 9, 0, 0, 0, 0, 0, 0, (void *) "Ring:", NULL, NULL },
12092 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12093 };
12094
12095 int32_t onIcons()
12096 {
12097 PALETTE pal;
12098 // pal = RAMpal;
12099 memcpy(pal,RAMpal,sizeof(RAMpal));
12100 icon_dlg[0].dp2=get_zc_font(font_lfont);
12101
12102 for(int32_t i=0; i<4; i++)
12103 {
12104 icon_dlg[i+2].d1 = QMisc.icons[i];
12105 icon_dlg[i+2].fg = i+6;
12106 load_cset(pal, i+6, pSprite(i+spICON1));
12107 }
12108
12109 zc_set_palette(pal);
12110
12111 large_dialog(icon_dlg);
12112
12113 int32_t ret = do_zqdialog(icon_dlg,7);
12114
12115 if(ret==6)
12116 {
12117 for(int32_t i=0; i<4; i++)
12118 {
12119 if(QMisc.icons[i] != icon_dlg[i+2].d1)
12120 {
12121 QMisc.icons[i] = icon_dlg[i+2].d1;
12122 saved=false;
12123 }
12124 }
12125 }
12126
12127 zc_set_palette(RAMpal);
12128 return D_O_K;
12129 }
12130
12131 // Identical to jwin_frame_proc, but is treated differently by large_dialog()
12132 int32_t d_comboframe_proc(int32_t msg, DIALOG *d, int32_t)
12133 {
12134 if(msg == MSG_DRAW)
12135 {
12136 jwin_draw_frame(screen, d->x, d->y, d->w, d->h, d->d1);
12137 }
12138
12139 return D_O_K;
12140 }
12141
12142 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t)
12143 {
12144 switch(msg)
12145 {
12146 case MSG_CLICK:
12147 {
12148 if((d->flags&D_NOCLICK))
12149 break;
12150
12151 int32_t ret = (d->flags & D_EXIT) ? D_CLOSE : D_O_K;
12152 int32_t combo2;
12153 int32_t cs;
12154
12155 if(CHECK_ALT) //place selected cmb/cs
12156 {
12157 if(gui_mouse_b()&1)
12158 {
12159 if(!CHECK_SHIFT)
12160 d->d1 = Combo;
12161 d->fg = CSet;
12162 }
12163
12164 return ret|D_REDRAW;
12165 }
12166 else if(gui_mouse_b()&2||nextcombo_fake_click==2) //clear to 0/0
12167 {
12168 d->d1=0;
12169 d->fg=0;
12170 return ret|D_REDRAW;
12171 }
12172 else if(gui_mouse_b()&1||nextcombo_fake_click==1) //popup combo picker
12173 {
12174 combo2=d->d1;
12175 cs=d->fg;
12176
12177 if((CHECK_CTRL_CMD ? select_combo_3 : select_combo_2)(combo2, cs))
12178 {
12179 d->d1=combo2;
12180 d->fg=cs;
12181 }
12182
12183 return ret|D_REDRAW;
12184 }
12185 else return ret|D_REDRAWME;
12186 }
12187 break;
12188
12189 case MSG_DRAW:
12190 {
12191 d->w = 32;
12192 d->h = 32;
12193
12194 BITMAP *buf = create_bitmap_ex(8,16,16);
12195 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12196
12197 if(buf && bigbmp)
12198 {
12199 clear_bitmap(buf);
12200
12201 if(d->d1==-1) // Display curr_combo instead of combobuf
12202 {
12203 newcombo hold = combobuf[0];
12204 combobuf[0] = curr_combo;
12205 putcombo(buf,0,0,0,d->fg);
12206 combobuf[0] = hold;
12207 }
12208 else if(d->d1)
12209 {
12210 putcombo(buf,0,0,d->d1,d->fg);
12211 }
12212
12213 stretch_blit(buf, bigbmp, 0,0, 16, 16, 0, 0, d->w, d->h);
12214 destroy_bitmap(buf);
12215 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12216 destroy_bitmap(bigbmp);
12217 }
12218 }
12219 break;
12220 }
12221 return D_O_K;
12222 }
12223
12224 // Hey, let's have a few hundred more lines of code, why not.
12225
12226 #define MR_4BIT 0
12227 #define MR_8BIT 1
12228
12229 static byte massRecolorSrc4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12230 static byte massRecolorDest4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12231 static word massRecolor8BitCSets=0; // Which CSets are affected? One bit each.
12232
12233 static byte massRecolorSrc8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12234 static byte massRecolorDest8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12235
12236 static int32_t massRecolorDraggedColor=-1;
12237 static int32_t massRecolorCSet;
12238 static bool massRecolorIgnoreBlank=true;
12239 static byte massRecolorType=MR_4BIT;
12240
12241 // Shows the sets of colors to replace from/to.
12242 // D_CSET: Colors are 0-15 within the current CSet rather than absolute.
12243 // D_SETTABLE: Colors can be dragged and dropped onto this one.
12244 #define D_CSET D_USER
12245 #define D_SETTABLE (D_USER<<1)
12246 int32_t d_mr_cset_proc(int32_t msg, DIALOG* d, int32_t)
12247 {
12248 BITMAP* bmp=screen;
12249 int32_t colorWidth=(d->w-4)/16;
12250 byte* colors=static_cast<byte*>(d->dp);
12251
12252 switch(msg)
12253 {
12254 case MSG_DRAW:
12255 {
12256 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12257
12258 int32_t baseColor=((d->flags&D_CSET)!=0) ? massRecolorCSet*16 : 0;
12259 for(int32_t c=0; c<16; c++)
12260 {
12261 rectfill(bmp,
12262 d->x+2+c*colorWidth, d->y+2,
12263 d->x+2+((c+1)*colorWidth)-1, d->y+2+d->h-5,
12264 baseColor+colors[c]);
12265 }
12266 }
12267 break;
12268
12269 case MSG_LPRESS:
12270 {
12271 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12272
12273 if(x >= 0 && x < 16) //sanity check!
12274 {
12275 massRecolorDraggedColor=colors[x];
12276 }
12277 }
12278 break;
12279
12280 case MSG_LRELEASE: // This isn't exactly right, but it'll do...
12281 if((d->flags&D_SETTABLE)!=0 && massRecolorDraggedColor>=0)
12282 {
12283 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12284 if(x >= 0 && x < 16) //sanity check!
12285 {
12286 colors[x]=massRecolorDraggedColor;
12287 d->flags|=D_DIRTY;
12288 }
12289 }
12290 massRecolorDraggedColor=-1;
12291 break;
12292 }
12293
12294 return D_O_K;
12295 }
12296
12297 // Used for the full palette in 8-bit mode.
12298 static int32_t d_mr_palette_proc(int32_t msg, DIALOG* d, int32_t)
12299 {
12300 BITMAP* bmp=screen;
12301 int colorWidth=(d->w-4)/16;
12302 d->h = 4+(colorWidth*14);
12303 int colorHeight=colorWidth;
12304
12305 switch(msg)
12306 {
12307 case MSG_DRAW:
12308 {
12309 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12310 for(int cset=0; cset<=13; cset++)
12311 {
12312 for(int color=0; color<16; color++)
12313 {
12314 rectfill(bmp,
12315 d->x+2+color*colorWidth,
12316 d->y+2+cset*colorHeight,
12317 d->x+2+((color+1)*colorWidth)-1,
12318 d->y+2+((cset+1)*colorHeight)-1,
12319 cset*16+color);
12320 }
12321 }
12322 }
12323 break;
12324
12325 case MSG_LPRESS:
12326 {
12327 int cset=(gui_mouse_y()-(d->y+2))/colorHeight;
12328 int color=(gui_mouse_x()-(d->x+2))/colorWidth;
12329 massRecolorDraggedColor=cset*16+color;
12330 }
12331 break;
12332 }
12333
12334 return D_O_K;
12335 }
12336
12337 static DIALOG recolor_4bit_dlg[] =
12338 {
12339 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12340 { jwin_win_proc, 0, 0, 216, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12341
12342 // 1
12343 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12344 { d_mr_cset_proc, 10, 42, 196, 16, 0, 0, 0, D_CSET, 0, 0, (void *)massRecolorSrc4Bit, NULL, NULL },
12345 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12346 { d_mr_cset_proc, 10, 70, 196, 16, 0, 0, 0, D_CSET|D_SETTABLE, 0, 0, (void *)massRecolorDest4Bit, NULL, NULL },
12347
12348 // 5
12349 { jwin_text_proc, 12, 96, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Apply to which CSets in 8-bit tiles?", NULL, NULL },
12350 { jwin_check_proc, 12, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "0", NULL, NULL },
12351 { jwin_check_proc, 36, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "1", NULL, NULL },
12352 { jwin_check_proc, 60, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "2", NULL, NULL },
12353 { jwin_check_proc, 84, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "3", NULL, NULL },
12354 { jwin_check_proc, 108, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "4", NULL, NULL },
12355 { jwin_check_proc, 132, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "5", NULL, NULL },
12356 { jwin_check_proc, 156, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "6", NULL, NULL },
12357 { jwin_check_proc, 12, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "7", NULL, NULL },
12358 { jwin_check_proc, 36, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "8", NULL, NULL },
12359 { jwin_check_proc, 60, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "9", NULL, NULL },
12360 { jwin_check_proc, 84, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "10", NULL, NULL },
12361 { jwin_check_proc, 108, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "11", NULL, NULL },
12362 { jwin_check_proc, 132, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "12", NULL, NULL },
12363 { jwin_check_proc, 156, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "13", NULL, NULL },
12364
12365 // 20
12366 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12367 { jwin_func_button_proc, 14, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset4Bit },
12368 { jwin_button_proc, 82, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 8-bit mode", NULL, NULL },
12369 { jwin_button_proc, 44, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12370 { jwin_button_proc, 112, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12371
12372 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12373 };
12374
12375 #define MR4_SRC_COLORS 2
12376 #define MR4_DEST_COLORS 4
12377 #define MR4_8BIT_EFFECT_START 6
12378 #define MR4_IGNORE_BLANK 20
12379 #define MR4_RESET 21
12380 #define MR4_SWITCH 22
12381 #define MR4_OK 23
12382 #define MR4_CANCEL 24
12383
12384 static DIALOG recolor_8bit_dlg[] =
12385 {
12386 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12387 { jwin_win_proc, 0, 0, 288, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12388
12389 // 1
12390 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12391 { d_mr_cset_proc, 10, 42, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorSrc8Bit, NULL, NULL },
12392 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12393 { d_mr_cset_proc, 10, 70, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorDest8Bit, NULL, NULL },
12394 { d_mr_palette_proc, 144, 32, 132, 150, vc(15), vc(1), 0, 0, 0, 0, (void *) NULL, NULL, NULL },
12395
12396 // 6
12397 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12398 { jwin_func_button_proc, 50, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset8Bit },
12399 { jwin_button_proc, 118, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 4-bit mode", NULL, NULL },
12400 { jwin_button_proc, 80, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12401 { jwin_button_proc, 148, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12402
12403 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12404 };
12405
12406 #define MR8_SRC_COLORS 2
12407 #define MR8_DEST_COLORS 4
12408 #define MR8_PALETTE 5
12409 #define MR8_IGNORE_BLANK 6
12410 #define MR8_RESET 7
12411 #define MR8_SWITCH 8
12412 #define MR8_OK 9
12413 #define MR8_CANCEL 10
12414
12415 static void massRecolorInit(int32_t cset)
12416 {
12417 massRecolorDraggedColor=-1;
12418 massRecolorCSet=cset;
12419
12420 recolor_4bit_dlg[0].dp2=get_zc_font(font_lfont);
12421 recolor_8bit_dlg[0].dp2=get_zc_font(font_lfont);
12422
12423 for(int32_t i=0; i<=13; i++)
12424 {
12425 if((massRecolor8BitCSets&(1<<i))!=0)
12426 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags|=D_SELECTED;
12427 else
12428 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&=~D_SELECTED;
12429 }
12430
12431 if(massRecolorIgnoreBlank)
12432 {
12433 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags|=D_SELECTED;
12434 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags|=D_SELECTED;
12435 }
12436 else
12437 {
12438 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&=~D_SELECTED;
12439 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&=~D_SELECTED;
12440 }
12441
12442 large_dialog(recolor_4bit_dlg);
12443 large_dialog(recolor_8bit_dlg);
12444
12445 // Quick fix for large_dialog() screwing these up. It's ugly. Whatever.
12446 if((recolor_4bit_dlg[MR4_DEST_COLORS].w-4)%4!=0)
12447 {
12448 recolor_4bit_dlg[MR4_SRC_COLORS].x++;
12449 recolor_4bit_dlg[MR4_SRC_COLORS].w-=2;
12450 recolor_4bit_dlg[MR4_DEST_COLORS].x++;
12451 recolor_4bit_dlg[MR4_DEST_COLORS].w-=2;
12452
12453 recolor_8bit_dlg[MR8_SRC_COLORS].x++;
12454 recolor_8bit_dlg[MR8_SRC_COLORS].w-=2;
12455 recolor_8bit_dlg[MR8_DEST_COLORS].x++;
12456 recolor_8bit_dlg[MR8_DEST_COLORS].w-=2;
12457 recolor_8bit_dlg[MR8_PALETTE].x++;
12458 recolor_8bit_dlg[MR8_PALETTE].w-=2;
12459 recolor_8bit_dlg[MR8_PALETTE].y++;
12460 recolor_8bit_dlg[MR8_PALETTE].h-=2;
12461 }
12462 }
12463
12464 static void massRecolorApplyChanges()
12465 {
12466 massRecolor8BitCSets=0;
12467 for(int32_t i=0; i<=13; i++)
12468 {
12469 if((recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&D_SELECTED)!=0)
12470 massRecolor8BitCSets|=1<<i;
12471 }
12472
12473 if(massRecolorType==MR_4BIT)
12474 massRecolorIgnoreBlank=(recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&D_SELECTED)!=0;
12475 else
12476 massRecolorIgnoreBlank=(recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&D_SELECTED)!=0;
12477 }
12478
12479 static bool massRecolorSetup(int32_t cset)
12480 {
12481 massRecolorInit(cset);
12482
12483 // Remember the current colors in case the user cancels.
12484 int32_t oldDest4Bit[16], oldSrc8Bit[16], oldDest8Bit[16];
12485 for(int32_t i=0; i<16; i++)
12486 {
12487 oldDest4Bit[i]=massRecolorDest4Bit[i];
12488 oldSrc8Bit[i]=massRecolorSrc8Bit[i];
12489 oldDest8Bit[i]=massRecolorDest8Bit[i];
12490 }
12491
12492 byte type=massRecolorType;
12493 int32_t ret;
12494 do
12495 {
12496 HANDLE_CLOSE_ZQDLG();
12497 if(exiting_program) break;
12498 if(type==MR_4BIT)
12499 {
12500 ret=do_zqdialog(recolor_4bit_dlg, MR4_OK);
12501 if(ret==MR4_SWITCH)
12502 type=MR_8BIT;
12503 }
12504 else
12505 {
12506 ret=do_zqdialog(recolor_8bit_dlg, MR8_OK);
12507 if(ret==MR8_SWITCH)
12508 type=MR_4BIT;
12509 }
12510 } while(ret==MR4_SWITCH || ret==MR8_SWITCH);
12511
12512 if(ret!=MR4_OK && ret!=MR8_OK) // Canceled
12513 {
12514 for(int32_t i=0; i<16; i++)
12515 {
12516 massRecolorDest4Bit[i]=oldDest4Bit[i];
12517 massRecolorSrc8Bit[i]=oldSrc8Bit[i];
12518 massRecolorDest8Bit[i]=oldDest8Bit[i];
12519 }
12520 return false;
12521 }
12522
12523 // OK
12524 massRecolorType=type;
12525 massRecolorApplyChanges();
12526 return true;
12527 }
12528
12529 static void massRecolorApply4Bit(int32_t tile)
12530 {
12531 byte buf[256];
12532 unpack_tile(newtilebuf, tile, 0, true);
12533
12534 if(newtilebuf[tile].format==tf4Bit)
12535 {
12536 for(int32_t i=0; i<256; i++)
12537 buf[i]=massRecolorDest4Bit[unpackbuf[i]];
12538 }
12539 else // 8-bit
12540 {
12541 for(int32_t i=0; i<256; i++)
12542 {
12543 word cset=unpackbuf[i]>>4;
12544 if((massRecolor8BitCSets&(1<<cset))!=0) // Recolor this CSet?
12545 {
12546 word color=unpackbuf[i]&15;
12547 buf[i]=(cset<<4)|massRecolorDest4Bit[color];
12548 }
12549 else
12550 buf[i]=unpackbuf[i];
12551 }
12552 }
12553
12554 pack_tile(newtilebuf, buf, tile);
12555 }
12556
12557 static void massRecolorApply8Bit(int32_t tile)
12558 {
12559 byte buf[256];
12560 unpack_tile(newtilebuf, tile, 0, true);
12561
12562 for(int32_t i=0; i<256; i++)
12563 {
12564 byte color=unpackbuf[i];
12565 for(int32_t j=0; j<16; j++)
12566 {
12567 if(massRecolorSrc8Bit[j]==color)
12568 {
12569 color=massRecolorDest8Bit[j];
12570 break;
12571 }
12572 }
12573 buf[i]=color;
12574 }
12575
12576 pack_tile(newtilebuf, buf, tile);
12577 }
12578
12579 static void massRecolorApply(int32_t tile)
12580 {
12581 if(massRecolorIgnoreBlank && blank_tile_table[tile])
12582 return;
12583
12584 if(massRecolorType==MR_4BIT)
12585 massRecolorApply4Bit(tile);
12586 else // 8-bit
12587 {
12588 if(newtilebuf[tile].format==tf4Bit)
12589 return;
12590 massRecolorApply8Bit(tile);
12591 }
12592 }
12593
12594 static void massRecolorReset4Bit()
12595 {
12596 for(int32_t i=0; i<16; i++)
12597 massRecolorDest4Bit[i]=i;
12598 recolor_4bit_dlg[MR4_DEST_COLORS].flags|=D_DIRTY;
12599 }
12600
12601 static void massRecolorReset8Bit()
12602 {
12603 for(int32_t i=0; i<16; i++)
12604 {
12605 massRecolorSrc8Bit[i]=0;
12606 massRecolorDest8Bit[i]=0;
12607 }
12608
12609 recolor_8bit_dlg[MR8_SRC_COLORS].flags|=D_DIRTY;
12610 recolor_8bit_dlg[MR8_DEST_COLORS].flags|=D_DIRTY;
12611 }
12612
12613 5 void center_zq_tiles_dialogs()
12614 {
12615 5 jwin_center_dialog(create_relational_tiles_dlg);
12616 5 jwin_center_dialog(icon_dlg);
12617 5 jwin_center_dialog(leech_dlg);
12618 5 jwin_center_dialog(move_textbox_list_dlg);
12619 5 jwin_center_dialog(recolor_4bit_dlg);
12620 5 jwin_center_dialog(recolor_8bit_dlg);
12621 5 }
12622
12623 //.ZCOMBO
12624
12625 int32_t readcombo_loop(PACKFILE* f, word section_version, newcombo& temp_combo);
12626 int32_t writecombo_loop(PACKFILE *f, word section_version, newcombo const& tmp_cmb);
12627
12628 int32_t readcombofile_old(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t zversion,
12629 dword section_version, dword section_cversion, int32_t index, int32_t count)
12630 {
12631 newcombo temp_combo;
12632 for ( int32_t tilect = 0; tilect < count; tilect++ )
12633 {
12634 temp_combo.clear();
12635 if(!p_igetw(&temp_combo.tile,f))
12636 {
12637 return 0;
12638 }
12639 temp_combo.o_tile = temp_combo.tile;
12640
12641 if(!p_getc(&temp_combo.flip,f))
12642 {
12643 return 0;
12644 }
12645
12646 if(!p_getc(&temp_combo.walk,f))
12647 {
12648 return 0;
12649 }
12650
12651 if(!p_getc(&temp_combo.type,f))
12652 {
12653 return 0;
12654 }
12655
12656 if(!p_getc(&temp_combo.csets,f))
12657 {
12658 return 0;
12659 }
12660
12661 if(!p_getc(&temp_combo.frames,f))
12662 {
12663 return 0;
12664 }
12665
12666 if(!p_getc(&temp_combo.speed,f))
12667 {
12668 return 0;
12669 }
12670
12671 if(!p_igetw(&temp_combo.nextcombo,f))
12672 {
12673 return 0;
12674 }
12675
12676 if(!p_getc(&temp_combo.nextcset,f))
12677 {
12678 return 0;
12679 }
12680
12681 if(!p_getc(&temp_combo.flag,f))
12682 {
12683 return 0;
12684 }
12685
12686 if(!p_getc(&temp_combo.skipanim,f))
12687 {
12688 return 0;
12689 }
12690
12691 if(!p_igetw(&temp_combo.nexttimer,f))
12692 {
12693 return 0;
12694 }
12695
12696 if(!p_getc(&temp_combo.skipanimy,f))
12697 {
12698 return 0;
12699 }
12700
12701 if(!p_getc(&temp_combo.animflags,f))
12702 {
12703 return 0;
12704 }
12705
12706 //2.55 starts here
12707 if ( zversion >= 0x255 )
12708 {
12709 if ( section_version >= 12 )
12710 {
12711 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12712 {
12713 if(!p_igetl(&temp_combo.attributes[q],f))
12714 {
12715 return 0;
12716 }
12717 }
12718 if(!p_igetl(&temp_combo.usrflags,f))
12719 {
12720 return 0;
12721 }
12722 for ( int32_t q = 0; q < 3; q++ )
12723 {
12724 if(!p_igetl(&temp_combo.triggerflags[q],f))
12725 {
12726 return 0;
12727 }
12728 }
12729
12730 if(!p_igetl(&temp_combo.triggerlevel,f))
12731 {
12732 return 0;
12733 }
12734 if(section_version >= 22)
12735 {
12736 if(!p_getc(&temp_combo.triggerbtn,f))
12737 {
12738 return 0;
12739 }
12740 }
12741 if(section_version < 23)
12742 {
12743 switch(temp_combo.type) //combotriggerCMBTYPEFX now required for combotype-specific effects
12744 {
12745 case cSCRIPT1: case cSCRIPT2: case cSCRIPT3: case cSCRIPT4: case cSCRIPT5:
12746 case cSCRIPT6: case cSCRIPT7: case cSCRIPT8: case cSCRIPT9: case cSCRIPT10:
12747 case cTRIGGERGENERIC: case cCSWITCH:
12748 temp_combo.triggerflags[0] |= combotriggerCMBTYPEFX;
12749 }
12750 }
12751 if(section_version >= 24)
12752 {
12753 if(!p_getc(&temp_combo.triggeritem,f))
12754 {
12755 return 0;
12756 }
12757 if(!p_getc(&temp_combo.trigtimer,f))
12758 {
12759 return 0;
12760 }
12761 }
12762 if(section_version >= 25)
12763 {
12764 if(!p_getc(&temp_combo.trigsfx,f))
12765 {
12766 return 0;
12767 }
12768 }
12769 else
12770 {
12771 switch(temp_combo.type)
12772 {
12773 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
12774 if(!(temp_combo.usrflags & cflag3))
12775 temp_combo.attribytes[3] = WAV_DOOR;
12776 temp_combo.usrflags &= ~cflag3;
12777 break;
12778 }
12779 }
12780 if(section_version < 26)
12781 {
12782 if(temp_combo.type == cARMOS)
12783 {
12784 if(temp_combo.usrflags & cflag1)
12785 temp_combo.usrflags |= cflag3;
12786 }
12787 }
12788 if(section_version >= 27)
12789 {
12790 if(!p_igetl(&temp_combo.trigchange,f))
12791 {
12792 return qe_invalid;
12793 }
12794 }
12795 else
12796 {
12797 if(temp_combo.triggerflags[0] & 0x00040000) //'next'
12798 temp_combo.trigchange = 1;
12799 else if(temp_combo.triggerflags[0] & 0x00080000) //'prev'
12800 temp_combo.trigchange = -1;
12801 else temp_combo.trigchange = 0;
12802 temp_combo.triggerflags[0] &= ~(0x00040000|0x00080000);
12803 }
12804 if(section_version >= 29)
12805 {
12806 if(!p_igetw(&temp_combo.trigprox,f))
12807 {
12808 return qe_invalid;
12809 }
12810 if(!p_getc(&temp_combo.trigctr,f))
12811 {
12812 return qe_invalid;
12813 }
12814 if(!p_igetl(&temp_combo.trigctramnt,f))
12815 {
12816 return qe_invalid;
12817 }
12818 }
12819 else
12820 {
12821 temp_combo.trigprox = 0;
12822 temp_combo.trigctr = 0;
12823 temp_combo.trigctramnt = 0;
12824 }
12825 if(section_version >= 30)
12826 {
12827 if(!p_getc(&temp_combo.triglbeam,f))
12828 {
12829 return qe_invalid;
12830 }
12831 }
12832 else temp_combo.triglbeam = 0;
12833 if(section_version >= 31)
12834 {
12835 if(!p_getc(&temp_combo.trigcschange,f))
12836 {
12837 return qe_invalid;
12838 }
12839 if(!p_igetw(&temp_combo.spawnitem,f))
12840 {
12841 return qe_invalid;
12842 }
12843 if(!p_igetw(&temp_combo.spawnenemy,f))
12844 {
12845 return qe_invalid;
12846 }
12847 if(!p_getc(&temp_combo.exstate,f))
12848 {
12849 return qe_invalid;
12850 }
12851 if(!p_igetl(&temp_combo.spawnip,f))
12852 {
12853 return qe_invalid;
12854 }
12855 if(!p_getc(&temp_combo.trigcopycat,f))
12856 {
12857 return qe_invalid;
12858 }
12859 }
12860 else
12861 {
12862 temp_combo.trigcschange = 0;
12863 temp_combo.spawnitem = 0;
12864 temp_combo.spawnenemy = 0;
12865 temp_combo.exstate = -1;
12866 temp_combo.spawnip = 0;
12867 temp_combo.trigcopycat = 0;
12868 }
12869 if(section_version >= 32)
12870 {
12871 if(!p_getc(&temp_combo.trigcooldown,f))
12872 {
12873 return qe_invalid;
12874 }
12875 }
12876 else
12877 {
12878 temp_combo.trigcooldown = 0;
12879 }
12880 char label[12];
12881 label[11] = '\0';
12882 for ( int32_t q = 0; q < 11; q++ )
12883 {
12884 if(!p_getc(&label[q],f))
12885 {
12886 return 0;
12887 }
12888 }
12889 temp_combo.label = label;
12890 }
12891 if ( section_version >= 13 )
12892 {
12893 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12894 {
12895 if(!p_getc(&temp_combo.attribytes[q],f))
12896 {
12897 return 0;
12898 }
12899 }
12900
12901 }
12902 }
12903
12904 if ( !(skip && (index+(tilect-1)) < skip) ) //is -1 still needed here?
12905 {
12906 if ( !nooverwrite || combobuf[index+tilect].is_blank() )
12907 {
12908 combobuf[index+(tilect)] = temp_combo;
12909 }
12910 }
12911 }
12912
12913 return 1;
12914 }
12915
12916 int32_t readcombofile(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t start)
12917 {
12918 dword section_version=0;
12919 dword section_cversion=0;
12920 int32_t zversion = 0;
12921 int32_t zbuild = 0;
12922
12923 if(!p_igetl(&zversion,f))
12924 {
12925 return 0;
12926 }
12927 if(!p_igetl(&zbuild,f))
12928 {
12929 return 0;
12930 }
12931 if(!p_igetw(&section_version,f))
12932 {
12933 return 0;
12934 }
12935 if(!p_igetw(&section_cversion,f))
12936 {
12937 return 0;
12938 }
12939
12940 if ( zversion > ZELDA_VERSION )
12941 {
12942 al_trace("Cannot read .zcombo packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
12943 return 0;
12944 }
12945
12946 else if ( ( section_version > V_COMBOS ) || ( section_version == V_COMBOS && section_cversion > CV_COMBOS ) )
12947 {
12948 al_trace("Cannot read .zcombo packfile made using V_COMBOS (%d) subversion (%d)\n", section_version, section_cversion);
12949 return 0;
12950
12951 }
12952 else
12953 {
12954 al_trace("Reading a .zcombo packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
12955 }
12956
12957 int32_t index = 0;
12958 int32_t count = 0;
12959
12960 //tile id
12961 if(!p_igetl(&index,f))
12962 {
12963 return 0;
12964 }
12965 if(start > -1) index = start;
12966 // al_trace("Reading combo: index(%d)\n", index);
12967
12968 //tile count
12969 if(!p_igetl(&count,f))
12970 {
12971 return 0;
12972 }
12973 // al_trace("Reading combo: count(%d)\n", count);
12974 reset_combo_animations();
12975 reset_combo_animations2();
12976
12977 if(section_version < 33)
12978 return readcombofile_old(f,skip,nooverwrite,zversion,section_version,section_cversion,index,count);
12979
12980 newcombo temp_combo;
12981 size_t end = index+count;
12982 for ( size_t q = index; q < end; q++ )
12983 {
12984 auto ret = readcombo_loop(f,section_version,temp_combo);
12985 if(ret) return 0;
12986
12987 if ( !(skip && q-1 < skip) )
12988 {
12989 if ( !nooverwrite || combobuf[q].is_blank() )
12990 {
12991 combobuf[q] = temp_combo;
12992 }
12993 }
12994 }
12995
12996 return 1;
12997 }
12998 int32_t readcombofile_to_location(PACKFILE *f, int32_t start, byte nooverwrite, int32_t skip)
12999 {
13000 return readcombofile(f,skip,nooverwrite,start);
13001 }
13002 int32_t writecombofile(PACKFILE *f, int32_t index, int32_t count)
13003 {
13004 dword section_version=V_COMBOS;
13005 dword section_cversion=CV_COMBOS;
13006 int32_t zversion = ZELDA_VERSION;
13007 int32_t zbuild = VERSION_BUILD;
13008
13009 if(!p_iputl(zversion,f))
13010 {
13011 return 0;
13012 }
13013 if(!p_iputl(zbuild,f))
13014 {
13015 return 0;
13016 }
13017 if(!p_iputw(section_version,f))
13018 {
13019 return 0;
13020 }
13021
13022 if(!p_iputw(section_cversion,f))
13023 {
13024 return 0;
13025 }
13026
13027 //start tile id
13028 if(!p_iputl(index,f))
13029 {
13030 return 0;
13031 }
13032
13033 //count
13034 if(!p_iputl(count,f))
13035 {
13036 return 0;
13037 }
13038 reset_combo_animations();
13039 reset_combo_animations2();
13040 size_t end = index+count;
13041 for(size_t q = index; q < end; ++q)
13042 {
13043 if(writecombo_loop(f, section_version, combobuf[q]))
13044 return 0;
13045 }
13046
13047 return 1;
13048
13049 }
13050
13051 //.ZALIAS
13052
13053
13054 //.ZALIAS
13055
13056 int32_t readcomboaliasfile(PACKFILE *f)
13057 {
13058 dword section_version=0;
13059 dword section_cversion=0;
13060 int32_t zversion = 0;
13061 int32_t zbuild = 0;
13062 word tempword = 0;
13063
13064 if(!p_igetl(&zversion,f))
13065 {
13066 return 0;
13067 }
13068 if(!p_igetl(&zbuild,f))
13069 {
13070 return 0;
13071 }
13072 if(!p_igetw(&section_version,f))
13073 {
13074 return 0;
13075 }
13076 if(!p_igetw(&section_cversion,f))
13077 {
13078 return 0;
13079 }
13080 al_trace("readoneweapon section_version: %d\n", section_version);
13081 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
13082
13083 if ( zversion > ZELDA_VERSION )
13084 {
13085 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13086 return 0;
13087 }
13088
13089 else if ( ( section_version > V_COMBOALIASES ) || ( section_version == V_COMBOALIASES && section_cversion > CV_COMBOALIASES ) )
13090 {
13091 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d) subversion (%d)\n", section_version, section_cversion);
13092 return 0;
13093
13094 }
13095 else
13096 {
13097 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13098 }
13099
13100 int32_t index = 0;
13101 int32_t count = 0;
13102 int32_t count2 = 0;
13103 byte tempcset = 0;
13104
13105 //tile id
13106 if(!p_igetl(&index,f))
13107 {
13108 return 0;
13109 }
13110 al_trace("Reading combo: index(%d)\n", index);
13111
13112 //tile count
13113 if(!p_igetl(&count,f))
13114 {
13115 return 0;
13116 }
13117 al_trace("Reading combo: count(%d)\n", count);
13118
13119 combo_alias temp_alias;
13120 memset(&temp_alias, 0, sizeof(temp_alias));
13121
13122 for ( int32_t tilect = 0; tilect < count; tilect++ )
13123 {
13124 memset(&temp_alias, 0, sizeof(temp_alias));
13125 if(!p_igetw(&temp_alias.combo,f))
13126 {
13127 return 0;
13128 }
13129
13130 if(!p_getc(&temp_alias.cset,f))
13131 {
13132 return 0;
13133 }
13134
13135
13136
13137 if(!p_igetl(&count2,f))
13138 {
13139 return 0;
13140 }
13141 al_trace("Read, Combo alias count is: %d\n", count2);
13142 if(!p_getc(&temp_alias.width,f))
13143 {
13144 return 0;
13145 }
13146
13147 if(!p_getc(&temp_alias.height,f))
13148 {
13149 return 0;
13150 }
13151
13152 if(!p_getc(&temp_alias.layermask,f))
13153 {
13154 return 0;
13155 }
13156 //These values are flexible, and may differ in size, so we delete them
13157 //and recreate them at the correct size on the pointer.
13158 temp_alias.combos.clear();
13159 temp_alias.csets.clear();
13160 for(int32_t k=0; k<count2; k++)
13161 {
13162 if(!p_igetw(&tempword,f))
13163 {
13164 //al_trace("Could not reas alias.combos[%d]\n",k);
13165 return 0;
13166 }
13167 else
13168 {
13169 //al_trace("Read Combo Alias Combo [%d] as: %d\n", k, tempword);
13170
13171
13172 //al_trace("tempword is: %d\n", tempword);
13173 temp_alias.combos[k] = tempword;
13174 //al_trace("Combo Alias Combo [%d] is: %d\n", k, temp_alias.combos[k]);
13175 }
13176 }
13177 //al_trace("Read alias combos.\n");
13178
13179 for(int32_t k=0; k<count2; k++)
13180 {
13181 if(!p_getc(&tempcset,f))
13182 //if(!p_getc(&temp_alias.csets[k],f))
13183 {
13184 return 0;
13185 }
13186 else
13187 {
13188 //al_trace("Read Combo Alias CSet [%d] as: %d\n", k, tempcset);
13189
13190 temp_alias.csets[k] = tempcset;
13191 //al_trace("Combo Alias CSet [%d] is: %d\n", k, temp_alias.csets[k]);
13192 }
13193 }
13194 //al_trace("Read alias csets.\n");
13195 //al_trace("About to memcpy a combo alias\n");
13196 memcpy(&combo_aliases[index+(tilect)],&temp_alias,sizeof(combo_alias));
13197 }
13198
13199 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
13200
13201
13202 return 1;
13203
13204 }
13205
13206 int32_t readcomboaliasfile_to_location(PACKFILE *f, int32_t start)
13207 {
13208 dword section_version=0;
13209 dword section_cversion=0;
13210 int32_t zversion = 0;
13211 int32_t zbuild = 0;
13212
13213 if(!p_igetl(&zversion,f))
13214 {
13215 return 0;
13216 }
13217 if(!p_igetl(&zbuild,f))
13218 {
13219 return 0;
13220 }
13221 if(!p_igetw(&section_version,f))
13222 {
13223 return 0;
13224 }
13225 if(!p_igetw(&section_cversion,f))
13226 {
13227 return 0;
13228 }
13229 al_trace("readcomboaliasfile_to_location section_version: %d\n", section_version);
13230 al_trace("readcomboaliasfile_to_location section_cversion: %d\n", section_cversion);
13231
13232 if ( zversion > ZELDA_VERSION )
13233 {
13234 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13235 return 0;
13236 }
13237 else if ( ( section_version > V_COMBOALIASES ) || ( section_version == V_COMBOALIASES && section_cversion > CV_COMBOALIASES ) )
13238 {
13239 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d) subversion (%d)\n", section_version, section_cversion);
13240 return 0;
13241
13242 }
13243 else
13244 {
13245 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13246 }
13247
13248 int32_t index = 0;
13249 int32_t count = 0;
13250 int32_t count2 = 0;
13251 byte tempcset = 0;
13252 word tempword = 0;
13253
13254
13255 //tile id
13256 if(!p_igetl(&index,f))
13257 {
13258 return 0;
13259 }
13260 al_trace("Reading tile: index(%d)\n", index);
13261
13262 //tile count
13263 if(!p_igetl(&count,f))
13264 {
13265 return 0;
13266 }
13267 al_trace("Reading tile: count(%d)\n", count);
13268
13269
13270 combo_alias temp_alias;
13271 memset(&temp_alias, 0, sizeof(temp_alias));
13272
13273 for ( int32_t tilect = 0; tilect < count; tilect++ )
13274 {
13275 memset(&temp_alias, 0, sizeof(temp_alias));
13276 if(!p_igetw(&temp_alias.combo,f))
13277 {
13278 return 0;
13279 }
13280
13281 if(!p_getc(&temp_alias.cset,f))
13282 {
13283 return 0;
13284 }
13285
13286 int32_t count2 = 0;
13287
13288 if(!p_igetl(&count2,f))
13289 {
13290 return 0;
13291 }
13292
13293 if(!p_getc(&temp_alias.width,f))
13294 {
13295 return 0;
13296 }
13297
13298 if(!p_getc(&temp_alias.height,f))
13299 {
13300 return 0;
13301 }
13302
13303 if(!p_getc(&temp_alias.layermask,f))
13304 {
13305 return 0;
13306 }
13307 //These values are flexible, and may differ in size, so we delete them
13308 //and recreate them at the correct size on the pointer.
13309 temp_alias.combos.clear();
13310 temp_alias.csets.clear();
13311
13312 for(int32_t k=0; k<count2; k++)
13313 {
13314 if(!p_igetw(&tempword,f))
13315 {
13316 return 0;
13317 }
13318 else
13319 {
13320 temp_alias.combos[k] = tempword;
13321 }
13322 }
13323
13324 for(int32_t k=0; k<count2; k++)
13325 {
13326 if(!p_getc(&tempcset,f))
13327 {
13328 return 0;
13329 }
13330 else
13331 {
13332 temp_alias.csets[k] = tempcset;
13333 }
13334 }
13335
13336 if ( start+(tilect) < MAXCOMBOALIASES )
13337 {
13338 memcpy(&combo_aliases[start+(tilect)],&temp_alias,sizeof(temp_alias));
13339 }
13340 }
13341 return 1;
13342 }
13343 int32_t writecomboaliasfile(PACKFILE *f, int32_t index, int32_t count)
13344 {
13345 al_trace("Running writecomboaliasfile\n");
13346 dword section_version=V_COMBOALIASES;
13347 dword section_cversion=CV_COMBOALIASES;
13348 int32_t zversion = ZELDA_VERSION;
13349 int32_t zbuild = VERSION_BUILD;
13350
13351 if(!p_iputl(zversion,f))
13352 {
13353 return 0;
13354 }
13355 if(!p_iputl(zbuild,f))
13356 {
13357 return 0;
13358 }
13359 if(!p_iputw(section_version,f))
13360 {
13361 return 0;
13362 }
13363
13364 if(!p_iputw(section_cversion,f))
13365 {
13366 return 0;
13367 }
13368
13369 //start tile id
13370 if(!p_iputl(index,f))
13371 {
13372 return 0;
13373 }
13374
13375 //count
13376 if(!p_iputl(count,f))
13377 {
13378 return 0;
13379 }
13380
13381 for ( int32_t tilect = 0; tilect < count; tilect++ )
13382 {
13383
13384 if(!p_iputw(combo_aliases[index+(tilect)].combo,f))
13385 {
13386 return 0;
13387 }
13388
13389 if(!p_putc(combo_aliases[index+(tilect)].cset,f))
13390 {
13391 return 0;
13392 }
13393
13394 int32_t count2 = ((combo_aliases[index+(tilect)].width+1)*(combo_aliases[index+(tilect)].height+1))*(comboa_lmasktotal(combo_aliases[index+(tilect)].layermask)+1);
13395
13396 if(!p_iputl(count2,f))
13397 {
13398 return 0;
13399 }
13400 al_trace("Write`, Combo alias count is: %d\n", count2);
13401
13402 if(!p_putc(combo_aliases[index+(tilect)].width,f))
13403 {
13404 return 0;
13405 }
13406
13407 if(!p_putc(combo_aliases[index+(tilect)].height,f))
13408 {
13409 return 0;
13410 }
13411
13412 if(!p_putc(combo_aliases[index+(tilect)].layermask,f))
13413 {
13414 return 0;
13415 }
13416
13417 for(int32_t k=0; k<count2; k++)
13418 {
13419 if(!p_iputw(combo_aliases[index+(tilect)].combos[k],f))
13420 {
13421 return 0;
13422 }
13423 }
13424
13425 for(int32_t k=0; k<count2; k++)
13426 {
13427 if(!p_putc(combo_aliases[index+(tilect)].csets[k],f))
13428 {
13429 return 0;
13430 }
13431 }
13432 }
13433
13434 return 1;
13435
13436 }
13437